Category: Uncategorized

  • Cloud Architect

    Ngày càng có nhiều công ty nghe thấy tiếng còi báo động của đám mây. Với chi phí khởi động thấp và dễ dàng thiết lập cơ sở hạ tầng, tại sao lại không?

    Nhưng khả năng loại bỏ phần cứng tại chỗ để chuyển sang sử dụng đám mây – nơi người khác phải tham gia vào việc bảo trì và cập nhật máy chủ – vẫn đòi hỏi các chuyên gia có thể làm cho mọi thứ hoạt động trơn tru.

    Chính xác thì kiến trúc sư đám mây là gì?

    “Khi bạn nghĩ về một kiến ​​trúc sư, bạn sẽ nghĩ đến một người nào đó thiết kế các tòa nhà và lên kế hoạch xây dựng chúng như thế nào; Meg Yahl, kỹ sư đám mây tại Uncomn, một công ty dịch vụ tư vấn công nghệ và quản lý doanh nghiệp cho biết.

    Cụ thể hơn, một kiến ​​trúc sư đám mây giúp một công ty phát triển, thực hiện và duy trì chiến lược điện toán đám mây của mình. Họ cần có hiểu biết sâu sắc về nhu cầu, ràng buộc, quy định ngành và mục tiêu của công ty họ vì nó liên quan đến điện toán đám mây.

    Susanne Tedrick, chuyên gia cơ sở hạ tầng đám mây tại Nền tảng điện toán đám mây Azure của Microsoft và trước đây là chuyên viên kỹ thuật tại IBM Cloud. Mặc dù bản thân không phải là kiến ​​trúc sư đám mây, Tedrick hợp tác chặt chẽ với các kiến ​​trúc sư đám mây trong quá trình giúp khách hàng sử dụng và di chuyển đám mây.

    Cô nói thêm rằng vai trò của kiến trúc sư đám mây đòi hỏi kiến thức kỹ thuật rất sâu về điện toán đám mây và các lĩnh vực bổ trợ như mạng máy tính, dữ liệu và bảo mật.

    Một số tiêu đề thường trùng lặp hoặc được coi là có thể hoán đổi cho nhau với các kiến trúc sư đám mây. Chúng bao gồm các kỹ sư đám mây và kiến trúc sư giải pháp trong các công ty hoặc phòng ban cụ thể về đám mây. Ví dụ: mặc dù chức danh của Yahl là kỹ sư đám mây – với các kỹ sư đám mây có xu hướng là những người thực hiện các thiết kế và kế hoạch do kiến trúc sư đám mây phát triển – cô ấy thường xuyên thực hiện cả các công việc dành riêng cho kỹ sư và kiến trúc sư.

    Tedrick ghi nhận phần lớn các biến thể tiêu đề và sự trùng lặp trong vai trò kiến trúc sư đám mây đối với sự phát triển nhanh chóng của nó khi việc áp dụng đám mây ngày càng phát triển.

    Bà nói: “Đặc biệt khi có những chuyên ngành phụ trong lĩnh vực này, các công ty sẽ thường kết hợp vai trò kiến trúc sư với trách nhiệm kỹ sư hoặc kỹ thuật viên.

    Không chỉ tương tác với đám mây

    Nói chung, trải nghiệm hàng ngày của kiến ​​trúc sư đám mây sẽ xoay quanh việc xác định, đáp ứng và thực hiện nhu cầu đám mây của công ty hoặc khách hàng, Tedrick nói. Điều này có thể có nghĩa là dẫn đầu các cuộc thảo luận chuyên sâu về kỹ thuật, xác nhận rằng giải pháp đám mây sẽ đáp ứng các yêu cầu của công ty hoặc xác định các cách giải quyết tiềm năng, phát triển sơ đồ kiến ​​trúc và giúp phát triển bằng chứng về công nghệ và bằng chứng về khái niệm cho khách hàng. Đôi khi, nó cũng có thể liên quan đến việc cung cấp sản phẩm chung và giáo dục điện toán đám mây.

    Đối với Frank Dagenhardt – kiến ​​trúc sư giải pháp cho Zscaler, một công ty bảo mật thông tin dựa trên đám mây – giáo dục những người khác về đám mây là một tính năng thường xuyên trong những ngày của ông. Điều này có thể liên quan đến việc viết sách trắng và bài đăng trên blog, hoặc tổ chức hội thảo trên web của nhóm người dùng trong ngành. Và các nỗ lực giảng dạy có thể hướng đến đối tượng nội bộ như nhân viên của Zscaler hoặc đối tác hoặc khách hàng bên ngoài.

    “Chúng tôi làm việc dựa trên sự hỗ trợ cho các nhóm nội bộ của chúng tôi và các đối tác của chúng tôi mà chúng tôi làm việc cùng – đảm bảo rằng họ hiểu các giải pháp, biết cách chúng hoạt động, những loại giải pháp khác nhau mà chúng tôi có thể giúp khách hàng và cách họ sẽ giúp khách hàng, ” Anh nói.

    Gặp gỡ khách hàng cũng là một phần chính trong các ngày của Dagenhardt. Anh và nhóm của mình thảo luận với khách hàng về nhu cầu của họ và cách đạt được những nhu cầu đó một cách tốt nhất. Các cuộc họp này thường tạo ra các ý tưởng để cải tiến các sản phẩm và dịch vụ của Zscaler, thông qua yêu cầu của khách hàng hoặc nhóm xác định các tính năng chung có thể phục vụ khách hàng tốt hơn.

    Dagenhardt cho biết: “Nếu có những khoảng trống về tính năng mà chúng tôi có thể mắc phải hoặc những thứ mà khách hàng đang tìm kiếm mà chúng tôi không giải quyết ngay hôm nay, thì chúng tôi có thể tiếp tục và đưa ra những đề xuất đó”.

    Việc chuyển đổi giữa giao tiếp với khách hàng và các nhóm kinh doanh kỹ thuật nội bộ đòi hỏi các kiến ​​trúc sư đám mây phải có kỹ năng giao tiếp mạnh mẽ. Vì kiến ​​trúc sư đám mây làm việc trên cơ sở hạ tầng kỹ thuật số cho phép một công ty hoạt động, họ có cơ hội tương tác và dẫn dắt các cuộc thảo luận kỹ thuật với nhiều đối tượng khác nhau như nhà phát triển, kỹ sư mạng, nhà quản lý, v.v.

    Đối với Yahl, công việc cơ sở hạ tầng là thứ chi phối cuộc sống của cô gần đây. Tại Uncomn, cô ấy đã tìm hiểu khá nhiều về cơ sở hạ tầng mạng và cách triển khai nó. Nhưng rất nhiều việc cô ấy đang làm gần đây đặc biệt liên quan đến rất nhiều cơ sở hạ tầng dưới dạng mã. Điều này giúp tăng tính nhất quán trong toàn công ty và giảm cơ hội mắc lỗi của con người.

    “Bạn muốn đảm bảo rằng nếu bạn cần tạo ra một ngăn xếp khác, một tập hợp máy chủ khác và tất cả những thứ đi kèm với nó, bạn muốn đảm bảo rằng bạn luôn làm theo cùng một cách,” cô nói.

    Học tập là một phần của thói quen hàng ngày

    Đó là kinh nghiệm phổ biến đối với các kiến ​​trúc sư đám mây.

    Yahl nói: “Cánh đồng khác nhau mỗi ngày. “Đó là một trong những điều mà nếu bạn không phấn đấu học hỏi, thì bạn sẽ bị tụt lại phía sau”.

    Dagenhardt cho biết tốc độ phát triển nhanh chóng của công nghệ đám mây là một trong những điều khiến anh ấy thức đêm. Ông chỉ ra rằng AWS đã mở rộng cung cấp của mình lên hơn 200 dịch vụ vào tháng 9. Và đó chỉ là một nhà cung cấp.

    Luôn cập nhật các tùy chọn, cách khách hàng có thể tận dụng các công nghệ mới và các phương pháp hay nhất có thể giúp bảo mật chúng, tất cả đều yêu cầu học hỏi liên tục. Đối với Dagenhardt, việc duy trì các chứng chỉ và học hỏi những điều mới khiến anh ấy cảm thấy mình luôn đứng đầu cuộc chơi.

    “Đó luôn là điều đã giúp ích cho tôi – dành một chút thời gian của tôi cho sự thăng tiến và cải thiện cá nhân,” anh nói.

    Yahl cũng nói về tầm quan trọng của việc tiếp tục học tập và các chứng chỉ của bạn, nhưng cô ấy cũng nhấn mạnh giá trị của việc học hỏi từ những người bạn làm việc cùng.

    “Các bạn học hỏi lẫn nhau, đặc biệt là các phím tắt hoặc công cụ giúp cuộc sống dễ dàng hơn,” cô nói, đồng thời đưa Visual Studio Code và ShellCheck làm ví dụ về các nguồn mà cô học được từ đồng nghiệp.

    Nhưng cô ấy nói rằng không chỉ đơn thuần là chọn những công cụ hữu ích có thể giúp một ngày trở nên dễ dàng hơn. Ngoài ra còn có yếu tố hợp tác là có được những quan điểm khác nhau về cách sử dụng hoặc triển khai các công nghệ khác nhau.

    “Khi bạn đang làm việc một mình, bạn đang ở trong khoảng trống và bạn không có ai để xem mã của mình, không ai để đảm bảo rằng bạn đang tuân thủ các phương pháp hay nhất tốt nhất có thể hoặc biết về những cách làm mới và đang phát triển Yahl nói.

    Trong những tình huống mà một kiến ​​trúc sư đám mây có thể không có đồng nghiệp để học hỏi từ đó, Yahl đề xuất những địa điểm như Reddit, nơi những người khác trong cộng đồng công nghệ đến để đặt câu hỏi cho nhau về các tài nguyên tốt nhất cho các tình huống khác nhau.

    “Về cơ bản, bạn có một danh sách những thứ mà mọi người sẽ giới thiệu và sau đó bạn nhận được quan điểm của người khác về những điều tốt và xấu về những công cụ đó và có một cuộc trò chuyện diễn ra liên tục,” cô nói. “Vì vậy, ngay cả khi bạn không có đồng nghiệp hướng dẫn, bạn vẫn có thể nhìn thấy nhiều quan điểm đó.”

    Mối quan tâm về bảo mật trong lĩnh vực đa đám mây, phát triển nhanh

    Hiểu và có thể làm việc trên nhiều nền tảng là nhu cầu ngày càng tăng đối với các kiến ​​trúc sư đám mây. Dagenhardt khuyên những người sẽ là kiến ​​trúc sư đám mây nên có sự kết hợp giữa các quan điểm khi nói đến nền tảng đám mây vì đó là nơi anh ấy nhìn thấy tương lai của lĩnh vực này.

    “Những gì chúng tôi đã thấy trong ngành công nghiệp đám mây là, trong khi hầu hết khách hàng bắt đầu từ một nhà cung cấp đám mây duy nhất, theo thời gian, họ trở thành một môi trường đa đám mây, nơi họ lưu trữ một số tài nguyên của mình trong một hoặc nhiều đám mây,” ông nói. Ông cũng nói rằng ông đang thấy sự thay đổi ngày càng tăng từ cơ sở hạ tầng như một dịch vụ sang các thùng chứa hoặc thậm chí là các công nghệ không máy chủ.

    Theo Tedrick, xu hướng đa dạng hóa đám mây này, các chiến lược và các yếu tố dựa trên đám mây khác như “cuộc chiến điện toán đám mây lớn hơn giữa AWS, Google và Microsoft” sẽ khiến vai trò kiến ​​trúc sư đám mây trở nên thịnh hành. Điều này có nghĩa là các nhà tuyển dụng đang tìm kiếm kiến ​​trúc sư đám mây sẽ muốn biết các kiến ​​trúc sư có kinh nghiệm thực hành về nền tảng đám mây nào.

    Bảo mật trong môi trường ngày càng mở rộng và không có kỹ thuật này đang và sẽ tiếp tục là mối quan tâm của những người làm việc với đám mây.

    Yahl nói: “Chúng tôi sẽ có những tính toán trong thế giới an ninh, đó là điều chắc chắn. “Có rất nhiều người muốn tham gia vào lĩnh vực này và họ học những kiến ​​thức cơ bản của họ, nhưng họ không học được sự bảo mật đằng sau nó.”

    Điều này một phần là do tốc độ của trường đám mây vượt xa khả năng của hầu hết các nền giáo dục chính quy trong việc cập nhật đào tạo về bảo mật, nhưng cũng bởi vì đám mây, theo Yahl, “rào cản gia nhập thấp nhất đối với bất kỳ ai cần thiết lập cơ sở hạ tầng của họ. ”

    Bà nói: “Đám mây rất tuyệt vời để quay các máy chủ và cơ sở hạ tầng và tất cả điều đó thực sự, rất nhanh chóng và thực sự dễ dàng,” cô nói, đồng thời cho biết thêm rằng nhiều giá trị mặc định trong môi trường đám mây có thể không an toàn. “Đám mây là một cách để thiết lập và chạy rất nhanh nhưng bạn cũng phải bảo mật nó.”

    Tốc độ tiến bộ của công nghệ đám mây cũng khiến Dagenhardt đặt ra các câu hỏi bảo mật về tương lai.

    Ông nói: “Chúng tôi vẫn có công nghệ cũ hơn và kế thừa hơn mà chúng tôi phải có khả năng xử lý và thích ứng. “Làm cách nào để chúng ta bảo vệ môi trường truyền thống cũng như bảo vệ môi trường đám mây và đảm bảo rằng nó có thể quản lý được và không tạo ra gấp đôi công việc cho khách hàng?”

    Làm thế nào để trở thành một kiến trúc sư đám mây

    Nếu không ngừng học hỏi và thích ứng với nhu cầu thay đổi của khách hàng và cảnh quan đám mây đang phát triển nghe có vẻ hấp dẫn, thì có một số lời khuyên cần ghi nhớ. Tedrick cho biết: Đứng đầu trong số đó là các kiến ​​trúc sư đám mây phải biết và hiểu rõ về điện toán đám mây ngoài những điều cơ bản.

    “Họ sẽ cần hiểu các phương pháp hay nhất về bảo mật đám mây doanh nghiệp, quản trị, tối ưu hóa chi phí, kiến ​​trúc đám mây kết hợp – sử dụng môi trường đám mây và tại chỗ – và kiến ​​trúc đa đám mây – sử dụng hai hoặc nhiều đám mây”, cô nói. “Trải nghiệm thực tế trên nền tảng đám mây nơi họ đang tạo và giám sát tài nguyên là điều bắt buộc, ưu tiên một năm kinh nghiệm trở lên.”

    Đối với những người không có cơ hội làm việc trên đám mây tại chỗ, Tedrick đã đề xuất các nền tảng bài học trực tuyến như A Cloud Guru và Pluralsight để cung cấp cho người dùng trải nghiệm thực tế với các nền tảng đám mây khác nhau.

    Khi đề cập đến việc ứng tuyển vai trò kiến ​​trúc sư đám mây, Yahl cho biết những người tìm việc không nên nản lòng nếu một bài đăng bao gồm các yêu cầu bạn không có hoặc liên quan đến các nhiệm vụ bạn không quen thuộc. Cô cũng chỉ ra rằng các tin tuyển dụng đôi khi không được viết bởi các chuyên gia kỹ thuật và yêu cầu những điều không thể. Đây có thể là một cái gì đó giống như yêu cầu nhiều năm kinh nghiệm trong một sản phẩm hơn nó đã tồn tại.

    “Nếu bạn đang muốn dấn thân vào lĩnh vực này, đừng để điều gì khiến bạn sợ hãi về vị trí mà bạn có hầu hết các kỹ năng,” cô khuyên.

    Yahl cũng khuyến khích những người muốn tham gia vào lĩnh vực kiến ​​trúc đám mây để thể hiện kỹ năng của họ và thực tế là họ đã phát triển và thay đổi trong những năm qua. Cô ấy chỉ ra Github hoặc các nền tảng khác nơi người dùng có thể lưu trữ mã là những nơi tuyệt vời để tạo danh mục đầu tư mã hóa.

    Chứng chỉ rất quan trọng đối với các kiến ​​trúc sư đám mây tiềm năng. Đây có thể là nhà cung cấp cụ thể và nhà cung cấp bất khả tri. Các chứng nhận tổng quát hơn có thể hữu ích cho thông tin chung và các phương pháp hay nhất về đám mây, nhưng theo Dagenhardt, các chứng chỉ dành riêng cho nhà cung cấp thường hữu ích hơn vì chúng sẽ giải quyết các sản phẩm đám mây cụ thể và các phương pháp hay nhất của chúng.

    Tedrick cũng chỉ ra rằng các chứng chỉ của các nhà cung cấp chính – Microsoft, AWS, Google và IBM – có nhiều khả năng được các nhà tuyển dụng tiềm năng công nhận hơn.

    Nhưng cô ấy nhấn mạnh rằng “mục tiêu phải là đạt được kỹ năng và kinh nghiệm thay vì đạt được chứng chỉ, vì chứng chỉ sẽ chỉ giúp bạn có được cho đến nay, và các kiến ​​trúc sư vĩ đại được sinh ra từ thử thách, sai lầm và thời gian.”

    Cảm ơn mọi người đã theo dõi. Author: DuongVT19.

  • [Flutter] Bố cục Layout (Phần 3)

    Container

    Một trong những Widget được sử dụng nhiều nhất – và vì những lý do này:

    Container as a layout tool

    Khi bạn không chỉ định height và width của Container, nó sẽ khớp với child kích thước của nó

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Container as a layout')),
        body: Container(
          color: Colors.yellowAccent,
          child: Text("Hi"),
        ),
      );
    }

    Nếu bạn muốn kéo dài Container để khớp với cha của nó, hãy sử dụng double.infinity cho các thuộc tính heightwidth

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Container as a layout')),
        body: Container(
          height: double.infinity,
          width: double.infinity,
          color: Colors.yellowAccent,
          child: Text("Hi"),
        ),
      );
    }

    Container as decoration

    Bạn có thể sử dụng thuộc tính color để làm thay đổi màu nền của Container bằng decoration và foregroundDecoration.

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Container.decoration')),
        body: Container(
          height: double.infinity,
          width: double.infinity,
          decoration: BoxDecoration(color: Colors.yellowAccent),
          child: Text("Hi"),
        ),
      );
    }

    . . .

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Container.foregroundDecoration')),
        body: Container(
          height: double.infinity,
          width: double.infinity,
          decoration: BoxDecoration(color: Colors.yellowAccent),
          foregroundDecoration: BoxDecoration(
            color: Colors.red.withOpacity(0.5),
          ),
          child: Text("Hi"),
        ),
      );
    }

    Container as Transform

    Nếu bạn không muốn sử dụng widget Transform để thay đổi bố cục của mình, bạn có thể sử dụng transform thuộc tính từ Container

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Container.transform')),
        body: Container(
          height: 300,
          width: 300,
          transform: Matrix4.rotationZ(pi / 4),
          decoration: BoxDecoration(color: Colors.yellowAccent),
          child: Text(
            "Hi",
            textAlign: TextAlign.center,
          ),
        ),
      );
    }

    . . .

    BoxDecoration

    BoxDecoration thường được sử dụng trên tiện ích Container để thay đổi diện mạo của Container.

    image: DecorationImage

    Đặt một hình ảnh làm nền:

    Scaffold(
      appBar: AppBar(title: Text('image: DecorationImage')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            color: Colors.yellow,
            image: DecorationImage(
              fit: BoxFit.fitWidth,
              image: NetworkImage(
                'https://flutter.io/images/catalog-widget-placeholder.png',
              ),
            ),
          ),
        ),
      ),
    );

    border: Border

    Chỉ định đường viền của Container sẽ trông như thế nào.

    Scaffold(
      appBar: AppBar(title: Text('border: Border')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            color: Colors.yellow,
            border: Border.all(color: Colors.black, width: 3),
          ),
        ),
      ),
    );

    borderRadius: BorderRadius

    Cho phép làm tròn các góc của đường viền.

    borderRadius không hoạt động nếu shape trong decoration là BoxShape.circle

    Scaffold(
      appBar: AppBar(title: Text('borderRadius: BorderRadius')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            color: Colors.yellow,
            border: Border.all(color: Colors.black, width: 3),
            borderRadius: BorderRadius.all(Radius.circular(18)),
          ),
        ),
      ),
    );

    shape: BoxShape

    BoxDecoration có thể là hình chữ nhật / hình vuông hoặc hình elip / hình tròn.

    Đối với bất kỳ hình dạng nào khác, bạn có thể sử dụng ShapeDecoration thay thế cho BoxDecoration

    Scaffold(
      appBar: AppBar(title: Text('shape: BoxShape')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            color: Colors.yellow,
            shape: BoxShape.circle,
          ),
        ),
      ),
    );

    boxShadow: List<BoxShadow>

    Thêm bóng vào Container .

    Tham số này là một danh sách vì bạn có thể chỉ định nhiều bóng khác nhau và hợp nhất chúng lại với nhau.

    Scaffold(
      appBar: AppBar(title: Text('boxShadow: List<BoxShadow>')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            color: Colors.yellow,
            boxShadow: const [
              BoxShadow(blurRadius: 10),
            ],
          ),
        ),
      ),
    );

    gradient

    Có ba loại gradient LinearGradient:, RadialGradientvà SweepGradient.

    Scaffold(
      appBar: AppBar(title: Text('gradient: LinearGradient')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: const [
                Colors.red,
                Colors.blue,
              ],
            ),
          ),
        ),
      ),
    );

    . . .

    Scaffold(
      appBar: AppBar(title: Text('gradient: RadialGradient')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            gradient: RadialGradient(
              colors: const [Colors.yellow, Colors.blue],
              stops: const [0.4, 1.0],
            ),
          ),
        ),
      ),
    );

    . . .

    Scaffold(
      appBar: AppBar(title: Text('gradient: SweepGradient')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          decoration: BoxDecoration(
            gradient: SweepGradient(
              colors: const [
                Colors.blue,
                Colors.green,
                Colors.yellow,
                Colors.red,
                Colors.blue,
              ],
              stops: const [0.0, 0.25, 0.5, 0.75, 1.0],
            ),
          ),
        ),
      ),
    );

    backgroundBlendMode

    backgroundBlendMode là tài sản phức tạp nhất của BoxDecoration.
    Nó chịu trách nhiệm trộn các màu / độ chuyển màu với nhau BoxDecorationvà bất cứ thứ gì BoxDecorationở trên cùng.

    Với backgroundBlendModebạn có thể sử dụng một danh sách dài các thuật toán được chỉ định trong BlendModeenum.

    Đầu tiên, hãy đặt BoxDecoration là foregroundDecoration

    Scaffold(
      appBar: AppBar(title: Text('backgroundBlendMode')),
      body: Center(
        child: Container(
          height: 200,
          width: 200,
          foregroundDecoration: BoxDecoration(
            backgroundBlendMode: BlendMode.exclusion,
            gradient: LinearGradient(
              colors: const [
                Colors.red,
                Colors.blue,
              ],
            ),
          ),
          child: Image.network(
            'https://flutter.io/images/catalog-widget-placeholder.png',
          ),
        ),
      ),
    );

    . . .

    Material

    Đường viền với các góc cắt

    Scaffold(
      appBar: AppBar(title: Text('shape: BeveledRectangleBorder')),
      body: Center(
        child: Material(
          shape: const BeveledRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(20)),
            side: BorderSide(color: Colors.black, width: 4),
          ),
          color: Colors.yellow,
          child: Container(
            height: 200,
            width: 200,
          ),
        ),
      ),
    );

    . . .

    Slivers

    SliverFillRemaining

    Widget này không thể thay thế khi bạn muốn căn giữa nội dung của mình ngay cả khi không có đủ dung lượng cho nó. Ví dụ

    Đủ không gian theo chiều dọc
    Scaffold(
      appBar: AppBar(title: Text('SliverFillRemaining')),
      body: CustomScrollView(
        slivers: [
          SliverFillRemaining(
            hasScrollBody: false,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                FlutterLogo(size: 200),
                Text(
                  'This is some longest text that should be centered'
                  'together with the logo',
                  textAlign: TextAlign.center,
                ),
              ],
            ),
          ),
        ],
      ),
    );

    Trong trường hợp không có đủ không gian cho nội dung được căn giữa, nội dung SliverFillRemaining sẽ có thể cuộn được:

    Nếu không có SliverFillRemaining nội dung sẽ tràn như thế này:

    Làm đầy không gian còn lại

    Ngoài việc hữu ích cho việc căn giữa nội dung của bạn, SliverFillRemaining nó sẽ lấp đầy không gian trống còn lại của khung nhìn. Để làm được điều đó, widget này phải được đặt vào CustomScrollView và cần phải là mảnh cuối cùng

    Trong trường hợp không có đủ dung lượng, tiện ích con sẽ có thể cuộn được:

    Scaffold(
      appBar: AppBar(title: Text('SliverFillRemaining')),
      body: CustomScrollView(
        slivers: [
          SliverList(
            delegate: SliverChildListDelegate(const [
              ListTile(title: Text('First item')),
              ListTile(title: Text('Second item')),
              ListTile(title: Text('Third item')),
              ListTile(title: Text('Fourth item')),
            ]),
          ),
          SliverFillRemaining(
            hasScrollBody: false,
            child: Container(
              color: Colors.yellowAccent,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const [
                  FlutterLogo(size: 200),
                  Text(
                    'This is some longest text that should be centered'
                    'together with the logo',
                    textAlign: TextAlign.center,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );

    . . .

    SizedBox

    Đây là một trong những Widget đơn giản nhưng hữu ích nhất

    SizedBox dưới dạng ConstrainedBox

    SizedBox có thể hoạt động theo cách tương tự như ConstrainedBox

    SizedBox.expand(
      child: Card(
        child: Text('Hello World!'),
        color: Colors.yellowAccent,
      ),
    ),

    . . .

    SizedBox dưới dạng padding

    Khi cần thêm phần đệm hoặc lề, bạn có thể chọn Padding hoặc Container các widget. Nhưng chúng có thể dài dòng hơn và khó đọc hơn so với việc thêm một Sizedbox

    Column(
      children: <Widget>[
        Icon(Icons.star, size: 50),
        const SizedBox(height: 100),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    SizedBox như một đối tượng vô hình

    Nhiều khi bạn muốn ẩn / hiện một tiện ích phụ thuộc vào bool

    Widget build(BuildContext context) {
      bool isVisible = ...
      return Scaffold(
        appBar: AppBar(
          title: Text('isVisible = $isVisible'),
        ),
        body: isVisible 
          ? Icon(Icons.star, size: 150) 
          : const SizedBox(),
      );
    }

    Vì SizedBox có một hàm const tạo nên việc sử dụng const SizedBox()thực sự rất tối ưu**.

    ** Một giải pháp tối ưu hơn sẽ là sử dụng Opacity widget và thay đổi opacity giá trị thành 0.0. Hạn chế của giải pháp này là tiện ích đã cho sẽ chỉ ẩn, vẫn chiếm không gian.

    . . .

    Trên các nền tảng khác nhau, có những khu vực đặc biệt như Thanh trạng thái trên Android hoặc Notch trên iPhone X mà chúng tôi có thể tránh vẽ dưới.

    Giải pháp cho vấn đề này là SafeArea widget (ví dụ không có / có SafeArea)

    Widget build(BuildContext context) {
      return Material(
        color: Colors.blue,
        child: SafeArea(
          child: SizedBox.expand(
            child: Card(color: Colors.yellowAccent),
          ),
        ),
      );
    }

    Kết thúc phần 3!

  • Giới thiệu FaunaDB

    FaunaDB là một lớp khác biệt với hầu hết các cơ sở dữ liệu xung quanh. Nó cung cấp tính linh hoạt và khả năng mở rộng đáng kinh ngạc. Vì FaunaDB không có máy chủ nên bạn có thể kết nối với cơ sở dữ liệu và sử dụng nó mà không cần lo lắng về bất kỳ điều gì khác.

    Bạn có thể sử dụng FaunaDB làm cơ sở dữ liệu OLTP (xử lý giao dịch trực tuyến) với ACID phân tán (tính nguyên tử, tính nhất quán, tính cách ly, độ bền), làm cơ sở dữ liệu tài liệu hoặc thậm chí là NoSQL dựa trên khóa-giá trị đơn giản. Nó cũng bao gồm hỗ trợ cho các tính năng doanh nghiệp như lưu giữ dữ liệu có thể định cấu hình và cho thuê nhiều lần theo thứ bậc.

    Quan trọng là, FaunaDB không ràng buộc bạn với đám mây. Nó có sẵn dưới dạng dịch vụ đám mây được quản lý hoặc JAR có thể tải xuống, hình ảnh máy hoặc vùng chứa mà bạn có thể chạy tại chỗ.

    Chức năng của FaunaDB

    FaunaDB cung cấp tính linh hoạt cao, cho phép bạn tinh chỉnh một số thông số dựa trên các yêu cầu của dự án của bạn. Chúng ta có thể sử dụng FaunaDB làm cơ sở dữ liệu quan hệ truyền thống, cơ sở dữ liệu khóa-giá trị, dựa trên tài liệu hoặc đồ thị. Chúng ta có thể thực thi một lược đồ trên dữ liệu hoặc chỉ để nó lỏng lẻo.

    FaunaDB là cực kỳ linh hoạt. Chúng ta có thể chạy FaunaDB trên đám mây (dưới dạng cơ sở dữ liệu không máy chủ với cấp miễn phí phong phú), tại cơ sở hoặc dưới dạng cơ sở dữ liệu nhúng, ngay bên trong ứng dụng của chúng ta. Cùng với những điểm cực đoan này, nó cũng cung cấp các hình thức triển khai phổ biến nhất như hình ảnh máy và hình ảnh docker.

    Tất cả điều này đi kèm với các giao dịch ACID và hiệu suất rất cao – mọi thứ mà một kiến trúc sư muốn cho một ứng dụng.

    Fauna Console

    Mặc dù Fauna cung cấp một trình bao lệnh thanh lịch cho đám mây DB (cơ sở dữ liệu), chúng ta hãy bắt đầu với bảng điều khiển web, đây là cách dễ dàng nhất để tham gia.

    Sau khi đăng ký, bạn sẽ thấy trang tổng quan giống như sau:

    Tạo cơ sở dữ liệu

    Để tạo cơ sở dữ liệu, bạn sẽ bắt đầu bằng cách nhấp vào Cơ sở dữ liệu mới (khá trực quan!). Sau khi bạn cung cấp tên DB, bạn đã hoàn tất; bây giờ bạn có một phiên bản DB mới cho ứng dụng của bạn. Nếu bạn chỉ muốn thực hành, bạn có thể chọn tùy chọn điền dữ liệu giả vào DB hoặc bạn có thể thêm dữ liệu của riêng mình.

    Với điều đó, bạn có một phiên bản cơ sở dữ liệu sạch.

    Tạo Collection.

    Tất nhiên, bước tiếp theo là tạo một bộ sưu tập. Fauna cung cấp một số lựa chọn khi chúng ta tạo một collection mới.

    Trang tạo collection trông giống như sau:

    Cùng với tên bộ sưu tập, chúng ta có hai tùy chọn. Ngày lịch sử và TTL (Thời gian tồn tại) cho mỗi bản ghi. Ngày lịch sử là số ngày Fauna sẽ lưu lại lịch sử của tài liệu (trong trường hợp bạn muốn hoàn tác thay đổi). Nếu chúng ta dọn sạch lĩnh vực này, lịch sử sẽ được lưu giữ mãi mãi. Đương nhiên, dữ liệu lịch sử cũng là dữ liệu được tính phí trên đám mây, vì vậy bạn phải cẩn thận khi chọn số này.

    TTL xác định số ngày mà một tài liệu chưa được chỉnh sửa ở lại trong bộ sưu tập sau lần viết cuối cùng. Việc đặt giá trị hợp lý cho TTL khá hữu ích vì nó có thể giúp giảm chi phí.

    Cuối cùng, chúng ta nhấn lưu và – bùng nổ – bạn đã tạo một bộ sưu tập mới. Bây giờ bạn sẽ thấy một giao diện người dùng sạch để thêm tài liệu mới vào bộ sưu tập.

    Tạo Document

    Nhấp vào nút đó sẽ hiển thị cho chúng ta một hộp văn bản nơi chúng ta có thể nhập JSON cho tài liệu mới mà chúng ta muốn thêm vào bộ sưu tập của mình.

    Bảng điều khiển cũng cung cấp một số tùy chọn khác để tạo chỉ mục, chức năng tùy chỉnh, thêm lược đồ GraphQL và cũng để tạo khóa bảo mật để truy cập cơ sở dữ liệu.

    Nếu bạn cảm thấy nhàm chán với giao diện người dùng, bảng điều khiển sẽ cung cấp liên kết để mở giao diện người dùng. Tại đây, chúng ta có thể gõ các lệnh cần thiết để làm việc với cơ sở dữ liệu. Trên thực tế, Fauna cũng cho phép chúng ta mở một trình bao trên thiết bị đầu cuối cục bộ của chúng ta để có thể tương tác với cơ sở dữ liệu. Hãy cùng kiểm tra nào.

    Fauna Shell

    Bất kỳ ai nghiêm túc về việc xây dựng các ứng dụng trong thế giới thực đều nên bỏ bảng điều khiển web và quay lại màn hình đen. Đó là cách tốt nhất để phát triển. Fauna cung cấp một CLI (giao diện dòng lệnh) rất tốt và một shell dựa trên NodeJS để giao tiếp với ứng dụng trên đám mây.

    Hãy bắt đầu với việc cài đặt. Nếu bạn đã hiểu được điều này, ta khá chắc chắn rằng bạn biết cách cài đặt NodeJS và npm (nếu chúng chưa được cài đặt). Vì vậy, hãy bắt đầu sau thời điểm đó. Chúng ta phải cài đặt Fauna shell bằng npm.

     Npm tập hợp tất cả những gì bạn cần để chạy Fauna shell và thiết lập nó.

    Tiếp theo, chúng ta đăng nhập vào tài khoản đám mây Fauna của mình.

    Điều này yêu cầu email và mật khẩu mà chúng ta đã sử dụng để đăng ký. Nó cũng có một tùy chọn để đăng nhập bằng một chìa khóa.

    QUERY DOCUMENTS

    Bây giờ, hãy thử tìm nạp các bản ghi từ bộ sưu tập. Có hai cách để truy vấn dữ liệu này. Bạn có thể sử dụng ID hoặc chỉ mục.

    Lưu ý trong các hoạt động tạo ở trên, chúng ta có một số – 270925464408687111 – trong xác nhận. Bạn có thể sử dụng điều này để truy vấn bản ghi.

    Điều này trả về bản ghi mà chúng ta vừa chèn.

    Tất nhiên, đây là một cách nhàm chán để truy vấn dữ liệu. Tại sao chúng ta tạo chỉ mục? Hãy sử dụng chỉ mục đó để truy vấn bản ghi được yêu cầu.

    Chúng ta có thể truy vấn cùng một bản ghi bằng cách sử dụng chỉ mục trên tiêu đề mà chúng ta đã tạo ở trên.

    Nó trả về cùng một bản ghi.

    Đó chỉ là một cái nhìn thoáng qua về những gì chúng ta có thể làm với bảng điều khiển web và shell. Fauna có tài liệu rất tốt. Bạn có thể xem Sách dạy nấu ăn trên trang web của họ để có một bộ sưu tập tốt các đoạn mã cho các trường hợp sử dụng khác nhau.

    Cảm ơn mọi người đã theo dõi.

    Author: DuongVT19

  • [Flutter] Bố cục Layout (Phần 2)

    [Flutter] Bố cục Layout (Phần 2)

    Tiếp tục phần trước, ta sẽ tiếp tục tìm hiểu thêm các widget giúp điều chỉnh bố cục hiển thị.

    IntrinsicWidth and IntrinsicHeight

    Tất cả tiện ích con bên trong Hàng hoặc Cột có chiều cao/rộng bằng tiện ích con cao nhất/rộng nhất

    Trong trường hợp bạn có kiểu bố trí này:

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('IntrinsicWidth')),
        body: Center(
          child: Column(
            children: <Widget>[
              RaisedButton(
                onPressed: () {},
                child: Text('Short'),
              ),
              RaisedButton(
                onPressed: () {},
                child: Text('A bit Longer'),
              ),
              RaisedButton(
                onPressed: () {},
                child: Text('The Longest text button'),
              ),
            ],
          ),
        ),
      );
    }

    Nhưng bạn muốn có tất cả các nút theo nút rộng nhất , chỉ cần sử dụng :IntrinsicWidth

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('IntrinsicWidth')),
        body: Center(
          child: IntrinsicWidth(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                RaisedButton(
                  onPressed: () {},
                  child: Text('Short'),
                ),
                RaisedButton(
                  onPressed: () {},
                  child: Text('A bit Longer'),
                ),
                RaisedButton(
                  onPressed: () {},
                  child: Text('The Longest text button'),
                ),
              ],
            ),
          ),
        ),
      );
    }

    Trong trường hợp bạn gặp vấn đề tương tự nhưng bạn muốn có tất cả các widget có chiều cao theo widget cao nhất chỉ cần sử dụng kết hợp của IntrinsicHeight và Row .

    IntrinsicWidthIntrinsicHeight còn được sử dụng để định kích thước con của nó theo chiều rộng/cao nội tại tối đa của nó. Nó có thể hữu ích nếu chiều rộng/cao khả dụng là không giới hạn, nhưng bạn muốn đặt kích thước của tiện ích con thành chiều rộng nội tại của nó.

    . . .

    Stack

    Chồng các Widget lên nhau

    @override
    Widget build(BuildContext context) {
      Widget main = Scaffold(
        appBar: AppBar(title: Text('Stack')),
      );
    
      return Stack(
        fit: StackFit.expand,
        children: <Widget>[
          main,
          Banner(
            message: "Top Start",
            location: BannerLocation.topStart,
          ),
          Banner(
            message: "Top End",
            location: BannerLocation.topEnd,
          ),
          Banner(
            message: "Bottom Start",
            location: BannerLocation.bottomStart,
          ),
          Banner(
            message: "Bottom End",
            location: BannerLocation.bottomEnd,
          ),
        ],
      );
    }

    . . .

    Bạn có thể các widget của mình vào Positioned Widget để xác định vị trí hiện thị

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Stack')),
        body: Stack(
          fit: StackFit.expand,
          children: <Widget>[
            Material(color: Colors.yellowAccent),
            Positioned(
              top: 0,
              left: 0,
              child: Icon(Icons.star, size: 50),
            ),
            Positioned(
              top: 340,
              left: 250,
              child: Icon(Icons.call, size: 50),
            ),
          ],
        ),
      );
    }

    . . .

    Nếu bạn không muốn đoán các giá trị trên cùng/dưới cùng, bạn có thể sử dụng LayoutBuilder để lấy chúng

    Widget build(BuildContext context) {
      const iconSize = 50;
      return Scaffold(
        appBar: AppBar(title: Text('Stack with LayoutBuilder')),
        body: LayoutBuilder(
          builder: (context, constraints) =>
            Stack(
              fit: StackFit.expand,
              children: <Widget>[
                Material(color: Colors.yellowAccent),
                Positioned(
                  top: 0,
                  child: Icon(Icons.star, size: iconSize),
                ),
                Positioned(
                  top: constraints.maxHeight - iconSize,
                  left: constraints.maxWidth - iconSize,
                  child: Icon(Icons.call, size: iconSize),
                ),
              ],
            ),
        ),
      );
    }

    . . .

    Expanded

    Expanded hoạt động với bố cục Flex\Flexbox và rất tốt để phân phối không gian giữa nhiều mục.

    Row(
      children: <Widget>[
        Expanded(
          child: Container(
            decoration: const BoxDecoration(color: Colors.red),
          ),
          flex: 3,
        ),
        Expanded(
          child: Container(
            decoration: const BoxDecoration(color: Colors.green),
          ),
          flex: 2,
        ),
        Expanded(
          child: Container(
            decoration: const BoxDecoration(color: Colors.blue),
          ),
          flex: 1,
        ),
      ],
    ),

    . . .

    ConstrainedBox

    Theo mặc định, hầu hết các tiện ích con sẽ sử dụng ít dung lượng nhất có thể:

    Card(child: const Text('Hello World!'), color: Colors.yellow)

    . . .

    ConstrainedBox cho phép tiện ích con sử dụng không gian còn lại như mong muốn.

    ConstrainedBox( 
      constraints: BoxConstraints.expand(),
      child: const Card(
        child: const Text('Hello World!'), 
        color: Colors.yellow,
      ), 
    ),

    . . .

    Bằng cách sử dụng BoxConstraints, bạn chỉ định lượng không gian mà một widget có thể có – bạn chỉ định minmax của heightwidth.

    BoxConstraints.expand sử dụng lượng không gian vô hạn (tất cả khả dụng) trừ khi được chỉ định:

    ConstrainedBox(
      constraints: BoxConstraints.expand(height: 300),
      child: const Card(
        child: const Text('Hello World!'), 
        color: Colors.yellow,
      ),
    ),

    Và nó giống như:

    ConstrainedBox(
      constraints: BoxConstraints(
        minWidth: double.infinity,
        maxWidth: double.infinity,
        minHeight: 300,
        maxHeight: 300,
      ),
      child: const Card(
        child: const Text('Hello World!'), 
        color: Colors.yellow,
      ),
    ),

    . . .

    Align

    Đôi khi bạn gặp khó khăn trong việc đặt tiện ích con của chúng tôi ở kích thước phù hợp – ví dụ: nó liên tục bị kéo căng khi bạn không muốn:

    Ví dụ ở trên xảy ra khi bạn có Column với CrossAxisAlignment.stretch và bạn chỉ muốn nút không bị kéo căng:

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Align: without Align')),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Align(
              child: RaisedButton(
                onPressed: () {},
                child: const Text('Button'),
              ),
            ),
          ],
        ),
      );
    }

    Khi tiện ích con của bạn không tuân theo các ràng buộc mà bạn cố gắng thiết lập, trước tiên hãy thử kết hợp với nó Align

    Kết thúc phần 2!

    . . .

  • [Flutter] Bố cục Layout (Phần 1)

    [Flutter] Bố cục Layout (Phần 1)

    Bạn cần các mẫu bố cục đơn giản cho Flutter?
    Tôi giới thiệu cho bạn tập hợp các đoạn mã bố cục Flutter của tôi. Tôi sẽ giữ cho nó ngắn gọn, dễ hiểu và đơn giản với vô số ví dụ trực quan.

    Row và Column

    MainAxisAlignment

    Row /*or Column*/( 
      mainAxisAlignment: MainAxisAlignment.start,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      mainAxisAlignment: MainAxisAlignment.end,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    CrossAxisAlignment

    Bạn nên sử dụng CrossAxisAlignment.baseline nếu bạn yêu cầu căn chỉnh đường cơ sở của các văn bản khác nhau

    Row(
      crossAxisAlignment: CrossAxisAlignment.baseline,
      textBaseline: TextBaseline.alphabetic,
      children: <Widget>[
        Text(
          'Baseline',
          style: Theme.of(context).textTheme.display3,
        ),
        Text(
          'Baseline',
          style: Theme.of(context).textTheme.body1,
        ),
      ],
    ),

    . . .

    Row /*or Column*/( 
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 200),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 200),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 200),
        Icon(Icons.star, size: 50),
      ],
    ),

    . . .

    Row /*or Column*/( 
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        Icon(Icons.star, size: 50),
        Icon(Icons.star, size: 200),
        Icon(Icons.star, size: 50),
      ],
    ),

    Kết thúc phần 1!

  • Quy trình phát triển phần mềm Scrum

    Quy trình phát triển phần mềm Scrum

    Scrum là một quy trình thực hiện hóa những giá trị và nguyên tắc của Agile

    1. Tổng quan về Scrum

    • Có một quy trình phát triển phần mềm truyền thống có tên là waterfall (mô hình thác nước)
    Waterfall Methodology. Waterfall Methodology | by Chathmini Jayathilaka |  Medium

    Quy trình này kéo dài từ đầu đến cuối trong quá trình phát triển phần mềm, và khách hàng sẽ phải chờ đợi đến phần cuối cùng của quy trình này để có thể nhìn thấy được sản phẩm của cả quá trình phát triển. Điều này là khá thụ động cho cả bên phía khách hàng và cho cả bên phát triển phần mềm.

    Minh chứng là khi tiếp nhận những sự thay đổi tại thời điểm cuối của quy trình sẽ có thể phải đập đi xây lại rất nhiều phần gây mất thêm thời gian maintain.

    Từ đó chúng ta mong muốn tạo ra một dự án “Deliverable Product” hay chính là sử dụng quy trình Scrum.

    • Chúng ta chia nhỏ dự án thành các Sprint (mỗi Sprint kéo dài trong vòng 1 đến 3 tuần)
    • Và cuối mỗi Sprint này chúng ta sẽ có một bản release, một bản chạy được để đưa cho khách hàng (dù nó chỉ là một chức năng nhỏ đã được hoàn thiện)
    • VD: Giả sự một phần mềm được phát triển trong vòng 6 tháng thì tương ứng sẽ có khoảng 24 Sprint và cùng với đó là 24 bản release để đưa cho khách hàng. Con số này lớn hơn rất nhiều so với mô hình waterfall
    • Việc đưa ra các bản release liên tục này sẽ giúp cho khách hàng có được cái nhìn tổng quan, khách quan hơn về sản phẩm đang được phát triển, đưa ra các feedback cho đội ngũ phát triển

    2. Ba Roles trong Scrum

    • Product Owner: Tập hợp tất cả yêu cầu khách hàng yêu cầu dự án phân chia các task theo thứ tự ưu tiên rồi giao cho đội ngũ phát triển.
    • Scrum Master: Giúp cho team làm việc tốt nhất, đảm bảo team đi đúng theo mô hình, quy trình đã đề ra.
    • Team: Gồm Dev, Tester, Content, …

    3. Ba Artifact trong Scrum

    • Product Backlog: Tất cả các task cần làm, các thông tin Product Owner lấy được từ khách hàng.
    • Sprint Backlog: Chứa các user story trong một Sprint, đã được chọn để làm trong Sprint
    • Burndown Chart: Chứa các task bạn làm trong một Sprint, đánh giá hiệu quả của Sprint
    Scrum Burndown Chart - Cách phân tích tiến độ & điều chỉnh sprint thông qua Burndown  Chart

    User Story: là một đặc tả một task dựa trên vị trí người dùng, nó mô tả những việc người dùng cần thao tác để đạt được điều mong muốn

    4. Ba Meeting trong Scrum

    • Sprint Planing: Bàn bạc về các task sẽ bỏ vào trong Sprint Backlog, dự đoán số điểm cho các User Story. Được tổ chức trước khi làm một Sprint.
    • Daily Scrum: Đồng bộ các tin tức, thông tin giữa mọi người trong dự án với nhau, đưa ra các vấn đề, trạng thái của task.
    • Sprint Review/Sprint Retrospective: Demo các task đã hoàn thành trong Sprint. Tìm ra những điểm đã làm tốt để phát huy và hạn chế những điểm chưa tốt.

    Quy trình chuẩn của một Sprint

    What is Scrum?

    5. Điểm lợi của Scrum

    • Luôn mang lại giá trị cao nhất cho người đầu tư dự án.
    • Năng suất lao động rất cao.

    Tài liệu tham khảo: Scrum cơ bản | Quy trình phát triển phần mềm | Ong Dev – YouTube

    Author: LamNT59

  • Chu trình phát triển phần mềm: Mô hình Waterfall (SDLC- Waterfall Model)

    Tổng quan:

    Mô hình Waterfall là mô hình vòng đời tuần tự tuyến tính. Nó rất đơn giản để hiểu và sử dụng. Trong mô hình Waterfall, mỗi giai đoạn phải được hoàn thành trước khi giai đoạn tiếp theo có thể bắt đầu và không có sự chồng chéo trong các giai đoạn.

    Mô hình Waterfall là cách tiếp cận SDLC (chu trình phát triền phần mêm) sớm nhất được sử dụng để phát triển phần mềm.

    Mô hình Waterfall minh họa quá trình phát triển phần mềm theo một dòng tuần tự tuyến tính. Điều này có nghĩa là bất kỳ giai đoạn nào trong quá trình phát triển chỉ bắt đầu nếu giai đoạn trước đó hoàn thành. Trong mô hình Waterfall này, các pha không chồng lên nhau.

    Thiết kế Waterfall Model

    Phương pháp tiếp cận mô hình Waterfall là Mô hình SDLC đầu tiên được sử dụng rộng rãi trong kỹ thuật phần mềm để đảm bảo sự thành công của dự án. Trong cách tiếp cận “The Waterfall”, toàn bộ quá trình phát triển phần mềm được chia thành các giai đoạn riêng biệt. Trong mô hình Waterfall này, thông thường, kết quả của một giai đoạn đóng vai trò là đầu vào cho giai đoạn tiếp theo một cách tuần tự.

    Hình minh họa sau đây là đại diện cho các giai đoạn khác nhau của Mô hình Waterfall.

    Các giai đoạn tuần tự trong mô hình Waterfall là:

    • Thu thập và phân tích yêu cầu (Requirement Gathering and analysis): Tất cả các yêu cầu có thể có của hệ thống được phát triển đều được ghi lại trong giai đoạn này và được ghi lại trong tài liệu đặc tả yêu cầu.
    • Thiết kế hệ thống (System Design): Các thông số kỹ thuật yêu cầu từ giai đoạn đầu tiên được nghiên cứu trong giai đoạn này và thiết kế hệ thống đã được chuẩn bị. Thiết kế hệ thống này giúp xác định các yêu cầu phần cứng và hệ thống cũng như giúp xác định kiến trúc hệ thống tổng thể.
    • Thực hiện (Implementation): Với đầu vào từ thiết kế hệ thống, hệ thống được phát triển đầu tiên trong các chương trình nhỏ được gọi là các đơn vị, được tích hợp trong giai đoạn tiếp theo. Mỗi đơn vị được phát triển và kiểm tra chức năng của nó, được gọi là Kiểm thử đơn vị (Unit test).
    • Tích hợp và Kiểm tra (Integration and Testing) Tất cả các đơn vị được phát triển trong giai đoạn triển khai được tích hợp vào một hệ thống sau khi thử nghiệm của từng đơn vị. Sau khi tích hợp, toàn bộ hệ thống được kiểm tra xem có bất kỳ lỗi và hỏng hóc nào không.
    • Triển khai hệ thống (Deployment of system) Sau khi kiểm tra chức năng và phi chức năng được thực hiện; sản phẩm được triển khai trong môi trường khách hàng hoặc được tung ra thị trường.
    • Bảo trì (Maintenance) Có một số vấn đề xảy ra trong môi trường khách hàng. Để khắc phục những vấn đề đó, các bản vá được phát hành. Ngoài ra để nâng cao sản phẩm một số phiên bản tốt hơn được phát hành. Bảo trì được thực hiện để mang lại những thay đổi này trong môi trường khách hàng.

    Tất cả các giai đoạn này được xếp tầng với nhau, trong đó tiến trình được xem như chảy đều đặn xuống dưới (giống như Waterfall) qua các giai đoạn. Giai đoạn tiếp theo chỉ được bắt đầu sau khi đạt được tập hợp mục tiêu đã xác định cho giai đoạn trước và nó được ký kết, vì vậy có tên “Mô hình Waterfall”. Trong mô hình này, các giai đoạn không chồng chéo lên nhau.

    Ứng dụng mô hình Waterfall.

    Mỗi phần mềm được phát triển đều khác nhau và đòi hỏi phải tuân theo một cách tiếp cận SDLC phù hợp dựa trên các yếu tố bên trong và bên ngoài. Một số tình huống mà việc sử dụng mô hình Waterfall là thích hợp nhất:

    • Các yêu cầu được ghi chép rất đầy đủ, rõ ràng và cố định.
    • Định nghĩa sản phẩm là ổn định.
    • Công nghệ được hiểu và không phải là năng động.
    • Không có yêu cầu mơ hồ.
    • Có sẵn các nguồn lực dồi dào với kiến thức chuyên môn cần thiết để hỗ trợ sản phẩm.
    • Dự án ngắn hạn.

    Ưu điểm của mô hình Waterfall.

    Ưu điểm của phát triển mô hình Waterfall là nó cho phép phân thành các phần và dễ dàng kiểm soát. Một lịch trình có thể được thiết lập với thời hạn cho từng giai đoạn phát triển và một sản phẩm có thể tiến hành từng giai đoạn của mô hình quy trình phát triển.

    Sự phát triển di chuyển từ khái niệm, thông qua thiết kế, thực hiện, thử nghiệm, cài đặt, khắc phục sự cố và kết thúc ở vận hành và bảo trì. Mỗi giai đoạn phát triển diễn ra theo thứ tự nghiêm ngặt.

    Một số ưu điểm chính của Mô hình Waterfall như sau:

    • Đơn giản và dễ để hiểu và sử dụng
    • Dễ dàng quản lý do độ cứng của mô hình. Mỗi giai đoạn có các phân phối cụ thể và một quy trình xem xét.
    • Các giai đoạn được xử lý và hoàn thành cùng một lúc.
    • Hoạt động tốt cho các dự án nhỏ hơn, nơi các yêu cầu được hiểu rất rõ.
    • Các giai đoạn được xác định rõ ràng.
    • Các mốc quan trọng được hiểu rõ.
    • Dễ dàng sắp xếp các công việc.
    • Quá trình và kết quả được ghi lại đầy đủ.

    Nhược điểm của mô hình Waterfall.

    Nhược điểm của phát triển Waterfall là nó không cho phép phản ánh hoặc sửa đổi nhiều. Một khi ứng dụng đang trong giai đoạn thử nghiệm, rất khó để quay lại và thay đổi điều gì đó không được ghi chép đầy đủ hoặc được nghĩ đến trong giai đoạn khái niệm.

    Những nhược điểm chính của Mô hình Waterfall như sau:

    • Không có phần mềm đang hoạt động nào được sản xuất cho đến cuối vòng đời.
    • Lượng rủi ro cao và không chắc chắn.
    • Không phải là một mô hình tốt cho các dự án hướng đối tượng và phức tạp.
    • Mô hình kém cho các dự án dài và đang diễn ra.
    • Không phù hợp với các dự án mà các yêu cầu có nguy cơ thay đổi từ trung bình đến cao. Vì vậy, rủi ro và sự không chắc chắn là cao với mô hình quy trình này.
    • Rất khó để đo lường sự tiến bộ trong các giai đoạn.
    • Không thể đáp ứng các yêu cầu thay đổi.
    • Điều chỉnh phạm vi trong vòng đời có thể kết thúc một dự án.
    • Việc tích hợp được thực hiện như một “vụ nổ lớn ở giai đoạn cuối, điều này không cho phép xác định sớm bất kỳ điểm nghẽn hoặc thách thức nào về công nghệ hoặc kinh doanh.

    Cảm ơn mọi người đã theo dõi.

    Author: DuongVT19

  • Backdrop Filter Widget trong Flutter

    Tạo hiệu ứng làm mờ bằng tiện ích BackdropFilter trong ứng dụng Flutter của bạn

    Chúng ta sẽ xem cách triển khai chương trình demo của BackdropFilter và hướng dẫn bạn cách sử dụng tiện ích đó để tạo hiệu ứng mờ trong các ứng dụng Flutter của bạn.

    Backdrop Filter Widget Flutter đang sử dụng để thực hiện các tác động làm mờ trên ảnh, container và mọi tiện ích. Tiện ích Backdrop Filter được sử dụng với sự kết hợp của lớp ImageFilter . Nó áp dụng một bộ lọc trên tiện ích con hiện tại và làm cho tác động mờ bên dưới tiện ích con hiện tại.

    Làm mờ hình ảnh:

    Chúng ta sẽ tạo tác động làm mờ sẽ được áp dụng cho toàn bộ không gian của tiện ích con. Khi BackdropFilter áp dụng bộ lọc, phần lớn chúng ta cần sử dụng tiện ích Stack để thực thi. Tiện ích mà bộ lọc sẽ được áp dụng phải được đặt trước bộ lọc.

    Stack(
      fit: StackFit.expand,
      children: <Widget>[
        Image.asset("assets/devs.jpg",fit: BoxFit.contain,),
        Positioned.fill(
          child: Center(
            child: BackdropFilter(
              filter: ImageFilter.blur(
                sigmaX: 10.0,
                sigmaY: 10.0,
              ),
              child: Container(
                color: Colors.black.withOpacity(0.2),
    
              ),
            ),
          ),
        ),
      ],
    ),

    Vì bộ lọc sẽ bao phủ toàn bộ không gian gốc của nó, chúng ta cần bao bọc tiện ích con BackdropFilter làm phần tử con của Positioned.fill. Bạn cần chứa ImageFilter. Đối với tình huống này, bộ lọc thích hợp nhất có thể được sử dụng ImageFilter.blursigmaX và sigmaY kiểm soát độ lệch tiêu chuẩn phụ thuộc vào bộ lọc trên trục x và trục y riêng lẻ. Cả hai đều có ước tính mặc định là 0, có nghĩa là không có tác động nào được áp dụng. Để áp dụng bộ lọc trên trục x, hãy thay đổi ước tính sigmaX thành một số dương. Đối với trục y, sử dụng thuộc tính sigmaY . Con của BackdropFilter có thể là một Container có độ mờ che bóng dưới 1, bằng 0 là giá trị điển hình. Khi chúng tôi chạy ứng dụng, chúng tôi phải lấy đầu ra của màn hình như ảnh chụp màn hình bên dưới.

    Làm mờ văn bản:

    Ví dụ Blur này là cách làm cho bộ lọc được áp dụng cho một không gian cụ thể của hình ảnh. Thay vì Positioned. fill , sử dụng hàm tạo mặc định của tiện ích con Positioned  mà bạn có thể đặt phân tách từ trên cùng, trái, dưới và phải. Trong mọi trường hợp, điều đó là không đầy đủ. Như tôi đã soạn ở trên, Flutter sẽ áp dụng bộ lọc cho tất cả các khoảng trống bên trong clip của tiện ích con của nó. Theo đó, để áp dụng kênh trên một lãnh thổ cụ thể, bạn cần bao bọc chúng BackdropFilter dưới dạng con của bất kỳ Clip widget, nào , như ClipRect, ClipRRect, ClipOval, ClipPath hoặc CustomClipper.

    Stack(
      fit: StackFit.expand,
      children: <Widget>[
        Image.asset("assets/devs.jpg",fit: BoxFit.contain,),
        Positioned(
          top: 250,
          left: 0,
          right: 0,
          child: Center(
            child: ClipRRect(
              borderRadius: BorderRadius.circular(24),
              child: BackdropFilter(
                filter: ImageFilter.blur(
                  sigmaX: 10.0,
                  sigmaY: 10.0,
                ),
                child: Container(
                  padding: EdgeInsets.all(24),
                  color: Colors.white.withOpacity(0.5),
                  child: Text(
                    "Flutter Dev's",
                    style: TextStyle(
                      fontSize: 28,
                      fontWeight: FontWeight.bold,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ],
    ),

    Chúng ta sẽ thêm văn bản trên một vùng chứa với độ mờ màu và bán kính đường viền sẽ là hình tròn do ClipRRect(). Khi ta chạy ứng dụng, ta phải lấy đầu ra của màn hình như ảnh chụp màn hình bên dưới.

    Làm mờ hình ảnh & văn bản:

    Trong hiệu ứng mờ này, tất cả mọi thứ sẽ giống nhau. Chúng tôi sẽ thêm Stack () , bên trong chúng tôi sẽ thêm một widget Positioned với trên cùng, bên trái và bên phải. Chúng tôi sẽ áp dụng BackdropFilter() và thuộc tính con của nó, chúng tôi sẽ thêm một container có cùng văn bản và màu sắc với độ mờ. Chúng tôi sẽ xóa ClipRRect. Tất cả các vật dụng sẽ bị mờ.

    Stack(
      fit: StackFit.expand,
      children: <Widget>[
        Image.asset("assets/devs.jpg",fit: BoxFit.contain,),
        Positioned(
          top: 250,
          left: 0,
          right: 0,
          child: Center(
            child: BackdropFilter(
              filter: ImageFilter.blur(
                sigmaX: 10.0,
                sigmaY: 10.0,
              ),
              child: Container(
                padding: EdgeInsets.all(24),
                color: Colors.white.withOpacity(0.5),
                child: Text(
                  "Flutter Dev's",
                  style: TextStyle(
                    fontSize: 28,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          ),
        ),
      ],
    ),

    Khi chạy ứng dụng, ta sẽ thấy màn hình như ảnh chụp màn hình bên dưới.

    Kết luận:

    Trong bài viết này, tôi đã giải thích cấu trúc cơ bản của widget BackdropFilter trong Flutter, bạn có thể sửa đổi mã này theo sự lựa chọn của bạn.

  • Mô hình Agile

    Mô hình Agile

    Có rất nhiều mô hình có thể áp dụng trong quá trình phát triển phần mềm, tuy nhiên Agile là một trong những mô hình đang được ứng dụng rất nhiều và phổ biến trong các công ty.

    1. Mô hình Agile là gì?

    Agile là một phương pháp phát triển phần mềm linh hoạt để làm sao đưa sản phẩm đến tay người dùng càng nhanh càng tốt.

    Tuyên ngôn Agile:

    Tuyên ngôn Agile hay còn gọi là Tuyên ngôn phát triển phần mềm linh hoạt, đánh giá cao:

    • Cá nhân và sự tương tác hơn là quy trình và công cụ.
    • Phần mềm chạy tốt hơn là tài liệu đầy đủ.
    • Cộng tác với khách hàng hơn là đàm phán hợp đồng.
    • Phản hồi với các thay đổi hơn là bám sát kế hoạch.

    Bên cạnh đó, các nhà phát triển còn nhấn mạnh hơn mười hai nguyên lý phía sau Tuyên ngôn Agile, để giúp các nhà phát triển vận dụng trong thực tiễn:

    • Ưu tiên cao nhất của chúng tôi là thỏa mãn khách hàng thông qua việc chuyển giao sớm và liên tục các phần mềm có giá trị.
    • Chào đón việc thay đổi yêu cầu, thậm chí rất muộn trong quá trình phát triển. Các quy trình linh hoạt tận dụng sự thay đổi cho các lợi thế cạnh tranh của khách hàng.
    • Thường xuyên chuyển giao phần mềm chạy tốt tới khách hàng. Từ vài tuần đến vài tháng, ưu tiên cho các khoảng thời gian ngắn hơn.
    • Nhà kinh doanh và nhà phát triển phải làm việc cùng nhau hàng ngày trong suốt dự án.
    • Xây dựng các dự án xung quanh những cá nhân có động lực. Cung cấp cho họ môi trường và sự hỗ trợ cần thiết, và tin tưởng họ để hoàn thành công việc.
    • Phương pháp hiệu quả nhất để truyền đạt thông tin tới nhóm phát triển và trong nội bộ nhóm phát triển là hội thoại trực tiếp.
    • Phần mềm chạy tốt là thước đo chính của tiến độ.
    • Các quy trình linh hoạt thúc đẩy phát triển bền vững. Các nhà tài trợ, nhà phát triển, và người dùng có thể duy trì một nhịp độ liên tục không giới hạn.
    • Liên tục quan tâm đến các kĩ thuật và thiết kế tốt để gia tăng sự linh hoạt.
    • Sự đơn giản – nghệ thuật tối đa hóa lượng công việc chưa xong – là căn bản.
    • Các kiến trúc tốt nhất, yêu cầu tốt nhất, và thiết kế tốt nhất sẽ được làm ra bởi các nhóm tự tổ chức.
    • Đội sản xuất sẽ thường xuyên suy nghĩ về việc làm sao để trở nên hiệu quả hơn. Sau đó họ sẽ điều chỉnh và thay đổi các hành vi của mình cho phù hợp.

    Có thể thấy mô hình Agile đặt khách hàng làm chủ đạo và tích cực trao đổi để tìm kiếm được sự hoàn thiện cho phần mềm.

    2. Đặc trưng của mô hình Agile

    Tính lặp

    Dự án sẽ được thực hiện trong các phân đoạn lặp đi lặp lại. Các phân đoạn (được gọi là Iteration hoặc Sprint) này thường có khung thời gian ngắn (từ 1 – 4 tuần).

    Trong mỗi phân đoạn này, nhóm phát triển thực hiện đầy đủ các công việc cần thiết như lập kế hoạch, phân tích yêu cầu, thiết kế, triển khai, kiểm thử (với các mức độ khác nhau) để cho ra các phần nhỏ của sản phẩm.

    Scrum Framework] Sprint là gì? - Scrum Viet

    Phân rã mục tiêu thành các phần nhỏ với quá trình lập kế hoạch đơn giản và gọn nhẹ nhất có thể

    Tính tăng trưởng và tiến hóa

    Cuối các phân đoạn (Sprint) nhóm phát triển thường cho ra các sản phẩm đầy đủ, có khả năng chạy tốt và được kiểm thử cẩn thận có thể sử dụng ngay.

    Đưa đến cho khách hàng góc nhìn chi tiết về tiến độ sản phẩm, từ đó có được sự tin tưởng từ khách hàng và có những thay đổi ngay lập tức với những yêu cầu của khách hàng.

    Tính thích nghi

    Các thay đổi trong quá trình phát triển có thể được đáp ứng một cách phù hợp, bởi vì các quy trình đã được phân chia rất rõ ràng và chi tiết.

    Nhóm tự tổ chức và liên chức năng

    Các nhóm này tự phân công công việc mà không dựa trên mô tả cứng về chức danh hay làm việc trên một phân cấp rõ ràng của tổ chức.

    Quản lý tiến trình thực nghiệm

    Các nhóm Agile đưa ra các quyết định dựa trên các dữ liệu thực tiễn thay vì lý thuyết hoặc các giả định. Từ đó giúp giảm quá trình phát triển và nâng cao năng suất lao động

    Giao tiếp trực diện

    Agile khuyến khích việc giao tiếp trực tiếp giữa nhóm phát triển với khách hàng, giữa các thành viên trong nhóm phát triển. Từ đó cùng nhau phát triển các chức năng một cách hiệu quả nhất

    Phát triển dựa trên giá trị

    Ưu tiên việc chạy tốt của sản phẩm, giao tiếp với khách hàng để biết yêu cầu nào được ưu tiên cao hơn, mang lại giá trị sớm nhất cho dự án.

    3. Ưu điểm của mô hình Agile

    • Thực hiện thay đổi dễ dàng: Bởi vì dự án được chia thành các phần nhỏ, riêng biệt, không phụ thuộc lẫn nhau, nên những thay đổi được thực hiện rất dễ dàng, ở bất kỳ giai đoạn nào của dự án.
    • Không cần phải nắm mọi thông tin ngay từ đầu: Phù hợp với những dự án chưa xác định được mục tiêu cuối cùng rõ ràng, vì việc này không quá cần thiết trong giai đoạn đầu.
    • Bàn giao nhanh hơn: Việc chia nhỏ dự án cho phép đội ngũ có thể tiến hành kiểm tra theo từng phần, xác định và sửa chữa vấn đề nhanh hơn, nhờ đó việc bàn giao công việc sẽ nhất quán và thành công hơn.
    • Chú ý đến phản hồi của khách hàng và người dùng: Cả khách hàng và người dùng cuối đều có cơ hội để đóng góp các ý kiến và phản hồi, từ đó họ sẽ có ảnh hưởng một cách mạnh mẽ và tích cực tới sản phẩm cuối cùng.
    • Cải tiến liên tục: Agile khuyến khích thành viên trong đội ngũ làm việc và khách hàng cung cấp phản hồi của mình, khi đó các giai đoạn khác nhau của sản phẩm cuối có thể được kiểm tra và cải thiện lại nhiều lần nếu cần.

    4. Nhược điểm của mô hình Agile

    • Khó lên kế hoạch dự án: Khá là khó để xác định rõ ràng thời gian bàn giao sản phẩm cuối cùng, vì dự án được chia nhỏ thành các phần khác nhau và mỗi phần lại có thời gian bàn giao riêng biệt.
    • Bắt buộc phải hướng dẫn và đào tạo chi tiết: Phương pháp Agile phức tạp hơn nhiều so với phương pháp truyền thống. Họ sẽ cần phải trải qua đào tạo, hướng dẫn thì mới có thể nắm được phương pháp một cách rõ ràng, đặc biệt là thời gian đầu.
    • Ít tài liệu hướng dẫn: Vì Agile thay đổi rất nhiều nên các tài liệu thích hợp cũng thường bị bỏ qua, vì không xác định rõ được kỳ vọng và thành phẩm ngay từ đầu. Mặc dù tài liệu không phải là yếu tố quan trọng nhất, nhưng chúng vẫn rất cần thiết.
    • Bắt buộc phải hợp tác để dự án thành công: Điều này đòi hỏi một sự cam kết về thời gian từ cả hai bên trong suốt thời gian của dự án mà các cấu trúc quản lý dự án khác không luôn yêu cầu. Phải có sự tham gia tích cực của người dùng và tiếp tục cộng tác để nó hoạt động.
    • Chi phí cao: Chi phí thực hiện theo phương pháp Agile thường hơn một chút so với các phương pháp phát triển khác.

    5. Áp dụng

    Để áp dụng thành công mô hình Agile trong tổ chức, chúng ta cần:

    • Thứ nhất, các thành viên phối hợp, giao tiếp hiệu quả trong nội bộ. Kỹ năng giao tiếp tốt giúp nhóm làm việc thấu hiểu khách hàng, hợp tác tốt với nhau đảm bảo chất lượng và tốc độ. 
    • Thứ hai, tính tự chủ của mỗi thành viên phải được đảm bảo để các nhóm tự quản lý có thể vận hành một cách chủ động, trơn tru thay vì chỉ tuân thủ theo chỉ dẫn cấp trên như trong các mô hình truyền thống. 
    • Thứ ba, các hoạt động được module hóa thông qua những nhóm liên chức năng. Những nhóm này có khả năng làm việc với tốc độ và chất lượng cao, với khách hàng là trung tâm

    Tham khảo:

    Author: LamNT59