Xin chào mọi người, dev.family đang liên lạc. Chúng tôi muốn kể cho bạn nghe về một dự án thú vị mà chúng tôi đã thực hiện gần sáu tháng và vẫn đang tiếp tục. Trong thời gian này, rất nhiều điều đã xảy ra trong đó, rất nhiều điều đã thay đổi. Chúng tôi đã khám phá ra một điều gì đó thú vị cho chính mình, đã xoay sở để lấp đầy những khúc mắc.
Câu chuyện của chúng ta sẽ như thế nào?
Vì vậy, những gì chúng ta vẫn đang làm việc trên? Trên thực tế, câu hỏi này tại một số thời điểm đã trở nên rất phù hợp, chẳng hạn như đối với chủ sở hữu của tập đoàn McDonalds một thời. Chúng tôi đã bắt đầu dự án dưới dạng chương trình khách hàng thân thiết bằng tiền điện tử cung cấp cho người dùng cuối phần thưởng cho một số hành động nhất định và khách hàng nhận được phân tích về chính những người dùng này. Vâng, nó khá hời hợt, nhưng nó không quan trọng.
Cần phải phát triển các mô-đun Shopify để kết nối với các cửa hàng Shopify, cổng thông tin cho các thương hiệu, tiện ích mở rộng cho Google Chrome, ứng dụng di động + máy chủ có cơ sở dữ liệu (thực ra, không nơi nào không có chúng). Nói chung, với những gì chúng tôi cần, chúng tôi đã quyết định và bắt tay vào làm. Vì dự án ngay lập tức được coi là lớn, nên mọi người đều hiểu rằng nó có thể phát triển như những hạt đậu thần nếu hành động bị trì hoãn.
Nó đã được quyết định làm mọi thứ "chính xác" và "theo tất cả các tiêu chuẩn". Đó là, mọi thứ được viết bằng một ngôn ngữ - TypeScript. Vì vậy, mọi người đều viết theo cùng một cách và không có thay đổi không cần thiết trong các tệp, linters (rất nhiều linters), để mọi thứ đều “dễ dàng” sử dụng lại, hãy đặt MỌI THỨ vào các mô-đun riêng biệt và để chúng không bị ăn cắp dưới mã thông báo truy cập Github.
Kho lưu trữ riêng cho linters và ts config (hướng dẫn kiểu)
Kho lưu trữ cho ứng dụng dành cho thiết bị di động (phản ứng gốc) và tiện ích mở rộng của Chrome (react.js) (cùng nhau, vì chúng lặp lại cùng một chức năng, chỉ nhằm vào những người dùng khác nhau)
Một kho lưu trữ khác cho cổng thông tin
Hai kho lưu trữ cho mô-đun Shopify
Kho lưu trữ cho công cụ blockchain Kho lưu trữ API (express.js) Kho lưu trữ cho cơ sở hạ tầng
Huh ... nghĩ rằng tôi đã liệt kê tất cả mọi thứ. Hóa ra hơi quá, nhưng không sao, chúng ta hãy tiếp tục lăn. Ồ vâng, tại sao hai kho lưu trữ được phân bổ cho các mô-đun Shopify? Bởi vì kho lưu trữ đầu tiên là các mô-đun giao diện người dùng. Có tất cả vẻ đẹp của những đứa trẻ sơ sinh của chúng ta và bối cảnh của chúng. Và thứ hai là tích hợp-Shopify. Trên thực tế, đây là cách triển khai của nó trong chính Shopify với tất cả các tệp lỏng. Tổng cộng, chúng tôi có 8 kho lưu trữ, trong đó một số nên giao tiếp với nhau.
Vì chúng ta đang nói về sự phát triển trong TypeScript, nên chúng ta cũng cần trình quản lý gói để cài đặt các mô-đun, thư viện. Nhưng tất cả chúng tôi đều làm việc độc lập trong các kho lưu trữ của mình và việc sử dụng cái gì không quan trọng với bất kỳ ai. Ví dụ: khi phát triển ứng dụng di động trên React Native, tôi đã không suy nghĩ quá lâu và giữ lại YARN1. Ai đó có thể quen với việc sử dụng NPM cũ tốt hơn, trong khi những người khác thích mọi thứ mới và sử dụng YARN3 mới. Do đó, ở đâu đó có NPM, ở đâu đó có YARN1 và ở đâu đó có YARN3.
Vì vậy, tất cả chúng tôi bắt đầu thực hiện các ứng dụng của mình. Và gần như ngay lập tức cuộc vui bắt đầu, nhưng không trọn vẹn. Đầu tiên, một số người không nghĩ TypeScript dùng để làm gì và sử dụng “Bất kỳ” ở bất cứ đâu họ quá lười biếng hoặc ở những nơi họ “không hiểu” về cách họ không thể viết nó. Ai đó đã không nhận ra tất cả sức mạnh của TypeScript và thực tế là ở một số nơi, mọi thứ có thể được thực hiện dễ dàng hơn nhiều. Do đó, các loại đã ra khỏi không gian vũ trụ. Vâng, tôi quên nói, chúng tôi đã quyết định sử dụng Hasura GraphQL làm cơ sở dữ liệu. Đánh máy thủ công tất cả các câu trả lời từ nó đôi khi trông giống như một cái gì đó khác. Và trong một trường hợp, một số thậm chí đã viết bằng Javascript cũ tốt. Vâng, tình hình trở nên thú vị: anh chàng đầu tiên đặt "Bất kỳ" một lần nữa để không quá căng thẳng, người thứ hai viết các loại vải bằng tay của chính mình, và người thứ ba vẫn không viết loại nào cả.
Sau đó, nó chỉ ra rằng trong những trường hợp chúng tôi lặp lại logic, và theo một cách tốt, nó nên được lấy ra trong một gói riêng - không ai sẽ làm điều này. Mọi người viết và viết mã cho chính mình, cho mọi thứ khác - nhổ từ tháp chuông cao.
Những gì chúng ta có? Chúng tôi có 8 kho lưu trữ với các ứng dụng khác nhau. Một số cần thiết ở mọi nơi, những người khác giao tiếp với nhau. Do đó, tất cả chúng ta đều tạo các tệp .NPMrc, quy định các khoản tín dụng, tạo mã thông báo github, sau đó thông qua mô-đun trình quản lý gói. Nói chung là một chút rắc rối, mặc dù khó chịu nhưng không có gì bất thường.
Chỉ trong trường hợp cập nhật thứ gì đó trong gói, bạn cần nâng cấp phiên bản của nó, sau đó tải nó lên, sau đó cập nhật nó trong ứng dụng/mô-đun của bạn và chỉ khi đó bạn mới thấy những gì đã thay đổi. Nhưng điều này là hoàn toàn không phù hợp! Đặc biệt là nếu bạn chỉ có thể thay đổi màu sắc ở đâu đó. Ngoài ra, một số mã được lặp lại và không được sử dụng lại mà chỉ được viết lại một cách lặng lẽ. Nếu chúng ta đang nói về một ứng dụng di động và tiện ích mở rộng trình duyệt, thì cửa hàng redux và tất cả công việc với API được lặp lại hoàn toàn ở đó, một số thứ chỉ được viết lại hoàn toàn hoặc sửa đổi một chút.
Tổng cộng, những gì chúng ta còn lại: một loạt kho lưu trữ, khởi chạy ứng dụng / mô-đun khá lâu, rất nhiều thứ giống nhau được viết bởi cùng một người, dành nhiều thời gian để thử nghiệm và giới thiệu người mới vào dự án, và các vấn đề khác phát sinh từ trên.
Nói tóm lại, điều này dẫn chúng ta đến thực tế là các nhiệm vụ đã được thực hiện trong một thời gian rất dài. Tất nhiên, điều này dẫn đến việc bỏ lỡ thời hạn, khá khó khăn để giới thiệu một người mới vào dự án, điều này một lần nữa ảnh hưởng đến tốc độ phát triển. Mọi thứ sẽ khá buồn tẻ và dài, trong một số trường hợp, nhờ có webpack cho điều đó.
Sau đó, rõ ràng là chúng tôi đang tiến xa khỏi nơi chúng tôi đang phấn đấu, nhưng ai biết được ở đâu. Sau khi phân tích tất cả các sai lầm, chúng tôi đã đưa ra một số quyết định sẽ được thảo luận ngay bây giờ.
Có lẽ, điều quan trọng nhất ảnh hưởng rất nhiều đến tương lai là nhận ra rằng chúng tôi không xây dựng một ứng dụng cụ thể mà là một nền tảng. Chúng tôi có một số loại người dùng, có các ứng dụng khác nhau dành cho họ, nhưng họ hoạt động trong cùng một nền tảng. Vì vậy, chúng tôi đã ngay lập tức đóng vấn đề với một số lượng lớn kho lưu trữ: nếu chúng tôi đang làm việc trên một nền tảng, tại sao lại chia nó thành các kho lưu trữ khi làm việc trong một kho lưu trữ dễ dàng hơn.
Tôi muốn nói rằng làm việc trong một doanh nghiệp độc quyền đã khiến cuộc sống của chúng tôi trở nên dễ dàng hơn rất nhiều. Một số ứng dụng hoặc mô-đun có mối quan hệ trực tiếp với nhau và giờ đây bạn có thể yên tâm làm việc với chúng trên cùng một nhánh trong cùng một kho lưu trữ. Nhưng đây là xa lợi thế chính.
Tiếp tục đi. Chúng tôi đã chuyển mọi thứ vào một kho lưu trữ. Mát mẻ! Chúng tôi tiếp tục làm việc với tốc độ như cũ cho đến khi đạt được khả năng tái sử dụng. Trên thực tế, đây là một “quy tắc về sở thích tốt” mà chúng tôi có trong công việc của mình. Nhận thấy rằng ở một số nơi, chúng tôi sử dụng cùng một thuật toán, chức năng, mã và ở một số nơi, các gói riêng biệt mà chúng tôi đã cài đặt qua github, chúng tôi quyết định rằng tất cả những thứ này “không được thơm cho lắm” và bắt đầu đặt mọi thứ vào các gói riêng biệt trong một đơn đăng ký sử dụng Không gian làm việc.
Không gian làm việc (workspaces) là tập hợp các chức năng trong NPM cli, nhờ đó bạn có thể quản lý nhiều gói từ một gói gốc cấp cao nhất.
Trên thực tế, đây là các gói bên trong một gói được liên kết thông qua một trình quản lý gói cụ thể (bất kỳ YARN / NPM / PNPM nào), sau đó được sử dụng trong một gói khác. Thành thật mà nói, chúng tôi đã không viết lại mọi thứ ngay lập tức trên không gian làm việc, nhưng đã làm điều đó khi cần thiết.
Từ một tập tin
{ "type": "module", "name": "package-name-1", ... "types": "./src/index.ts", "exports": { ".": "./src/index.ts" }, },
Đến một tập tin khác
{ "type": "module", "name": "package-name-2", ... "dependencies": { "package-name-1": "workspace:*", }, },
Một ví dụ sử dụng PNPM
Thực ra không có gì phức tạp nếu bạn nghĩ về nó: viết một vài lệnh và dòng, sau đó sử dụng bất cứ thứ gì bạn muốn và bất cứ nơi nào bạn muốn. Nhưng “có một lưu ý, thưa các đồng chí”. Trước đó tôi đã viết rằng mọi người đều sử dụng trình quản lý gói mà họ muốn. Nói tóm lại, chúng tôi có một kho lưu trữ với các trình quản lý khác nhau. Ở một số chỗ, thật buồn cười khi ai đó viết rằng anh ta không thể liên kết gói này hay gói kia, vì thực tế là anh ta sử dụng NPM và có YARN.
Tôi sẽ nói thêm rằng vấn đề không phải do các trình quản lý khác nhau mà do mọi người đã sử dụng sai lệnh hoặc cấu hình sai thứ gì đó. Ví dụ: một số người thông qua YARN 3 chỉ thực hiện một liên kết YARN và thế là xong, nhưng đối với YARN 1, nó không hoạt động theo cách họ muốn do thiếu khả năng tương thích ngược.
Đến thời điểm này, rõ ràng là sử dụng cùng một trình quản lý gói sẽ tốt hơn. Nhưng bạn cần chọn cái nào, vì vậy tại thời điểm đó, chúng tôi chỉ xem xét 2 tùy chọn - SỢI và PNPM . Chúng tôi đã loại bỏ NPM ngay lập tức, vì nó chậm hơn và xấu hơn những cái khác. Có sự lựa chọn giữa PNPM và YARN.
YARN ban đầu hoạt động tốt - nó nhanh hơn, đơn giản hơn và dễ hiểu hơn, đó là lý do tại sao sau đó mọi người đều sử dụng nó. Nhưng người tạo ra YARN đã rời Facebook và quá trình phát triển các phiên bản tiếp theo và nó đã được chuyển giao cho người khác. Đây là cách YARN 2 và YARN 3 xuất hiện mà không có khả năng tương thích ngược với YARN trước đây. Ngoài ra, ngoài tệp Yarn.lock, chúng tạo ra một thư mục Sợi, đôi khi có trọng lượng là node_modules và lưu trữ các bộ đệm trong chính nó.
Do đó, chúng tôi cũng như nhiều nhà phát triển khác đã chuyển sự chú ý sang PNPM. Hóa ra nó tiện lợi như SỢI đầu tiên vào thời điểm đó. Không gian làm việc có thể dễ dàng sử dụng ở đây, một số lệnh trông giống như trong YARN đầu tiên. Ngoài ra, đáng xấu hổ-hoist hóa ra là một tùy chọn bổ sung tuyệt vời - việc cài đặt node_modules ở mọi nơi cùng một lúc sẽ thuận tiện hơn là vào một thư mục nào đó mỗi lần và thực hiện cài đặt PNPM.
Ngoài ra, chúng tôi quyết định thử turborepo. Turborepo là một công cụ CI/CD có bộ tùy chọn, cli và cấu hình riêng thông qua tệp turbo.json. Cài đặt và cấu hình dễ dàng nhất có thể. Chúng tôi đặt một bản sao toàn cầu của turbo cli thông qua
PNPM add turbo --global.
Thêm turbo.json vào dự án
turbo.json
{ "$schema": "https://turbo.build/schema.json", "pipeline": { "build": { "dependsOn": ["^build"] } } }
Sau đó, chúng ta có thể sử dụng tất cả các chức năng có sẵn của turborepo. Chúng tôi bị thu hút nhất bởi các tính năng của nó và khả năng sử dụng nó trong một monorepo.
Các bản dựng tăng dần (Bản dựng tăng dần - việc thu thập các bản dựng khá khó khăn, Turborepo sẽ ghi nhớ những gì đã được xây dựng và bỏ qua những gì đã được tính toán);
Băm nhận biết nội dung (Content-aware hashing - Turborepo xem xét nội dung của các tệp, không phải ở dấu thời gian, để tìm ra những gì cần được xây dựng);
Bộ nhớ đệm từ xa (Băm từ xa - chia sẻ bộ đệm bản dựng từ xa với nhóm và CI / CD để tạo bản dựng nhanh hơn nữa.);
Đường dẫn nhiệm vụ (Một đường dẫn nhiệm vụ xác định mối quan hệ giữa các nhiệm vụ và sau đó tối ưu hóa nội dung và thời điểm tạo.).
Thực thi song song (Thực hiện các bản dựng sử dụng từng lõi với khả năng song song tối đa mà không lãng phí CPU nhàn rỗi).
Chúng tôi cũng đã lấy đề xuất tổ chức một monorepo từ tài liệu và triển khai nó trong nền tảng của chúng tôi. Đó là, chúng tôi chia tất cả các gói của mình thành các ứng dụng và gói. Để làm điều này, chúng tôi cũng tạo tệp PNPM-workspace.yaml và viết:
PNPM-workspace.yaml
packages:
'apps/**/*'
'packages/**/*'
Ở đây bạn có thể thấy một ví dụ về cấu trúc trước và sau của chúng tôi:
Bây giờ chúng ta có một monorep với không gian làm việc tùy chỉnh và tái sử dụng mã thuận tiện. Tôi sẽ bổ sung thêm một số điểm mà chúng tôi đã làm song song. Tôi đã đề cập đến hai điều trước đó: chúng tôi có tiện ích mở rộng chrome và chúng tôi đã quyết định rằng - chúng tôi đang tạo một nền tảng.
Vì nền tảng của chúng tôi làm việc với Shopify là ưu tiên hàng đầu nên chúng tôi đã quyết định rằng thay vì tiện ích mở rộng cho Chrome hoặc ngoài tiện ích đó, sẽ rất tuyệt nếu tạo một mô-đun khác cho Shopify, mô-đun này có thể được cài đặt đơn giản trên trang web, để không phải mất một lần lại buộc mọi người tải xuống ứng dụng dành cho thiết bị di động hoặc tiện ích mở rộng của Chrome . Nhưng nó phải hoàn toàn lặp lại phần mở rộng. Ban đầu, chúng tôi thực hiện chúng song song, nhưng chúng tôi nhận ra rằng chúng tôi đã làm sai điều gì đó, vì chúng tôi chỉ đơn giản là sao chép mã. Theo mọi nghĩa, chúng tôi viết cùng một thứ ở những nơi khác nhau. Tuy nhiên, vì hiện tại chúng tôi có tất cả không gian làm việc và cấu hình sử dụng lại nên chúng tôi dễ dàng di chuyển mọi thứ vào một gói mà chúng tôi đã gọi trong mô-đun Shopify và tiện ích mở rộng của Chrome. Vì vậy, chúng tôi đã tiết kiệm cho mình rất nhiều thời gian.
Điều thứ hai giúp chúng tôi tiết kiệm rất nhiều thời gian là việc loại bỏ webpack và, ở một số nơi, các bản dựng nói chung. Có gì sai với gói web? Trên thực tế, có hai điểm quan trọng: độ phức tạp và tốc độ. Những gì chúng tôi đã chọn là vite. Tại sao? Nó dễ cài đặt hơn, nó nhanh chóng trở nên phổ biến và đã có một số lượng lớn plugin đang hoạt động, và một ví dụ từ bến cảng là đủ để cài đặt. Để so sánh, quá trình xây dựng trên webpack của tiện ích web Chrome của chúng tôi mất khoảng 15 giây, trên vite.js
khoảng 7 giây (với tạo tệp dts).
Cảm nhận sự khác biệt. Điều gì xảy ra với việc từ chối các bản dựng? Mọi thứ đều đơn giản, vì hóa ra, chúng tôi không thực sự cần chúng, vì đây là những mô-đun có thể tái sử dụng và trong package.json, khi xuất, bạn chỉ cần thay thế dist/index.js bằng src/index.ts.
Nó như thế nào
{... "exports": { "import": "./dist/built-index.js" }, ... }
Bây giờ thế nào
{ ... "types": "./src/index.ts", "exports": { ".": "./src/index.ts" }, ... }
Do đó, chúng tôi đã loại bỏ nhu cầu chạy đồng hồ PNPM để theo dõi các cập nhật ứng dụng liên quan đến các mô-đun đó và thực hiện xây dựng PNPM để lấy các bản cập nhật. Tôi không nghĩ rằng nó đáng để giải thích nó đã tiết kiệm cho chúng tôi bao nhiêu thời gian.
Trên thực tế, một trong những lý do tại sao chúng tôi thu thập các bản dựng là TypeScript, chính xác hơn là các tệp index.d.ts. Vì vậy, khi nhập các mô-đun/gói của chúng tôi, chúng tôi biết loại nào được mong đợi trong các chức năng nhất định hoặc loại nào người khác sẽ trả lại cho chúng tôi, chẳng hạn như ở đây:
Nhưng do bạn chỉ có thể xuất từ index.tsx, nên có một lý do khác để từ bỏ các bản dựng.
Tuy nhiên, tại sao lại là TypeScript? Tôi nghĩ bây giờ không có ý nghĩa gì khi mô tả tất cả các ưu điểm của TS: an toàn kiểu, tạo điều kiện thuận lợi cho quá trình phát triển do gõ, sự hiện diện của các giao diện và lớp, mã nguồn mở, các lỗi mắc phải trong quá trình sửa đổi mã có thể nhìn thấy ngay lập tức và không phải trong thời gian chạy , và như thế.
Như tôi đã nói ngay từ đầu, chúng tôi quyết định viết mọi thứ bằng một ngôn ngữ để nếu ai đó ngừng làm việc hoặc nghỉ việc, chúng tôi có thể hỗ trợ hoặc bảo hiểm. Đầu tiên chúng tôi chọn JS. Nhưng JS không an toàn lắm và nếu không có các bài kiểm tra trên các dự án lớn thì điều đó khá khó khăn. Vì vậy, chúng tôi quyết định ủng hộ TS. Như thực tế đã chỉ ra, nó rất thuận tiện trong monorepo, do thực tế là bạn có thể xuất các tệp * .ts một cách đơn giản và khi sử dụng các thành phần, dữ liệu mong muốn và loại của chúng sẽ ngay lập tức rõ ràng.
Nhưng một trong những tính năng hữu ích chính là tự động tạo các loại cho truy vấn và đột biến GraphQl. Đối với những người không hiểu biết nhiều, GraphQl là một công nghệ cho phép bạn truy cập cơ sở dữ liệu thông qua cùng một truy vấn (để lấy dữ liệu) và đột biến (để thay đổi dữ liệu) và trông giống như sau:
query getShop {shop { shopName shopLocation } }
Không giống như API REST, nơi cho đến khi bạn nhận được nó, bạn sẽ không biết điều gì sẽ đến với mình, ở đây bạn tự xác định dữ liệu mình cần.
Hãy quay trở lại với Tổng thống đắc cử của chúng ta. Chúng tôi đã sử dụng Hasura, một trình bao bọc GraphQL trên PostgreSQL. Vì chúng tôi đang làm việc với TS, nên theo cách tốt nhất, chúng tôi phải nhập dữ liệu từ cả yêu cầu và dữ liệu mà chúng tôi gửi tới tải trọng. Nếu chúng ta đang nói về mã từ ví dụ trên, thì sẽ không có vấn đề gì. Nhưng trong thực tế, một truy vấn có thể lên tới hàng trăm dòng, cộng với một số trường có thể có hoặc không có hoặc có các loại dữ liệu khác nhau. Và gõ những bức tranh như vậy là một nhiệm vụ rất dài và vô nghĩa.
Thay thế? Tất nhiên tôi có! Hãy để các loại được tạo thông qua các lệnh. Trong dự án của chúng tôi, chúng tôi đã làm như sau:
Chúng tôi đã sử dụng các thư viện sau: graphql và graphql-request
Đầu tiên, các tệp có độ phân giải *.graphql được tạo, trong đó các truy vấn và biến đổi được viết.
Ví dụ:
thử nghiệm.graphql
query getAllShops {test_shops { identifier name location owner_id url domain type owner { name owner_id } } }
codegen.yaml
schema: ${HASURA_URL}:headers: x-hasura-admin-secret: ${HASURA_SECRET}
emitLegacyCommonJSImports: false
config: gqlImport: graphql-tag#gql scalars: numeric: string uuid: string bigint: string timestamptz: string smallint: number
generates: src/infrastructure/api/graphQl/operations.ts: documents: 'src/**/*.graphql'
plugins: - TypeScript - TypeScript-operations - TypeScript-graphql-request
Ở đó, chúng tôi đã chỉ ra nơi chúng tôi sẽ đến và ở cuối - nơi chúng tôi lưu tệp bằng API đã tạo (src/infrastructure/api/graphQl/operations.ts) và nơi chúng tôi nhận yêu cầu của mình từ đó (src/**/*. graphql).
Sau đó, một tập lệnh đã được thêm vào pack.json để tạo ra các loại tương tự cho chúng tôi:
gói.json
{... "scripts": { "generate": "HASURA_URL=http://localhost:9696/v1/graphql HASURA_SECRET=secret graphql-codegen-esm --config codegen.yml", ... }, ... }
Họ chỉ ra URL mà tập lệnh đã truy cập để lấy thông tin, bí mật và chính lệnh đó.
import { GraphQLClient } from "graphql-request"; import { getSdk } from "./operations.js"; export const createGraphQlClient = ({ getToken }: CreateGraphQlClient) => { const graphQLClient = new GraphQLClient('your url goes here...'); return getSdk(graphQLClient); };
Do đó, chúng tôi nhận được một hàm tạo ứng dụng khách với tất cả các truy vấn và đột biến. Phần thưởng trong hoạt động.ts đặt tất cả các loại của chúng tôi mà chúng tôi có thể xuất và sử dụng, đồng thời có một loại hoàn chỉnh cho toàn bộ yêu cầu: chúng tôi biết những gì cần đưa ra và điều gì sẽ đến. Bạn không cần phải suy nghĩ về bất cứ điều gì khác, ngoại trừ việc chạy lệnh và tận hưởng vẻ đẹp của việc gõ.
Do đó, chúng tôi đã loại bỏ một số lượng lớn các kho lưu trữ không cần thiết và nhu cầu liên tục thúc đẩy những thay đổi nhỏ nhất để kiểm tra xem mọi thứ hoạt động như thế nào. Thay vào đó, họ đã nghĩ ra một thứ trong đó mọi thứ được cấu trúc, phân tách theo mục đích của nó và mọi thứ đều có thể dễ dàng tái sử dụng. Vì vậy, chúng tôi đã làm cho cuộc sống của mình dễ dàng hơn và giảm thời gian giới thiệu những người mới về dự án, khởi chạy nền tảng và các mô-đun / ứng dụng riêng biệt. Mọi thứ đã được nhập và bây giờ không cần phải vào từng thư mục và xem chức năng/thành phần này hoặc chức năng kia muốn gì. Kết quả là, thời gian phát triển đã được giảm bớt.
Tóm lại, tôi muốn nói rằng bạn đừng bao giờ vội vàng. Tốt hơn là nên hiểu những gì bạn đang làm và làm thế nào để làm điều đó dễ dàng hơn là cố tình làm phức tạp cuộc sống của bạn. Các vấn đề ở khắp mọi nơi và luôn luôn, sớm hay muộn chúng sẽ xuất hiện ở đâu đó, và sau đó sự phức tạp có chủ ý sẽ bắn vào đầu gối bạn, nhưng sẽ không giúp được gì.
Nhóm dev.family đã đồng hành cùng bạn, hẹn gặp lại!