Tôi là Lydia, một cô gái 19 tuổi sống ở Stockholm, và tôi là một developer JavaScript (React)!
Tôi bắt đầu viết code từ lúc 15 tuổi. Đồng thời, tôi cũng có một blog về sức khoẻ và lối sống trên Tumblr với hàng chục ngàn người xem. Đây là lúc tôi bắt đầu tạo layout của riêng mình với HTML, CSS và jQuery. Do tôi không thích các themes có sẵn trên thị trường nên tôi đã quyết định tự lực gánh sinh! Kể từ đó, tôi tiếp tục nâng cao kỹ năng và kiến thức. Tuy nhiên, tôi không hề nghĩ rằng những việc này là coding bởi tôi chỉ đơn giản là thích tạo ra các thiết kế của riêng cho mình.
Trong thời gian này, tôi vẫn học chính qui cho đến khi được 18 tuổi. Tuy vậy, tôi cảm thấy như mình đã lãng phí rất nhiều thời gian cho các thứ hầu như chả mang lại ích lợi gì cho bản thân. Tuy vậy, tôi vẫn rất chăm chỉ để có bằng tốt nghiệp tốt cũng như làm thêm cho nhiều dự án bên lề.
Sau khi tốt nghiệp trung học, tôi quyết định không lên đại học. Đây là một quyết định rất đáng sợ đối với tôi, vì tôi luôn được nhồi ép rằng chỉ có đại học là cách duy nhất để có một tương lai thành công! Tôi đã dành rất nhiều thời gian để đạt được điểm số cao nhất trong trường trung học để có thể vào một trường đại học tốt. Và quả thật là tôi thực sự đã lãng phí rất nhiều năm trong cuộc đời mình. Nhưng tôi không hề hối tiếc! Hầu hết mọi người xung quanh tôi không hiểu và nghĩ tôi mắc phải một sai lầm lớn, nhưng vẫn có một số ít hiểu và ủng hộ tôi.
Bản thân vốn rất độc lập: do đó mà tôi đã chuyển đến một quốc gia khác khi tôi chỉ mới 18 tuổi. Song song đó, tôi cũng đi du lịch rất nhiều và luôn bận rộn làm bất cứ điều gì để cải thiện tương lai của mình. Sau khi tôi quyết định không đi học đại học, tôi đã tham gia chương trình đào tạo về code trong 3 tháng tại Tampa Bay, Florida. Nó đã giúp tôi rất nhiều khi củng cố một lượng kiến thức nền tảng quan trọng cũng như gặp gỡ những người bạn cùng niềm đam mê. Tôi đã học một cách điên cuồng, liên tục thử thách bản thân và đã nỗ lực rất nhiều vào các dự án cá nhân của tôi để cải thiện kỹ năng lập trình cũng như học được nhiều công nghệ mới.
Thật bất ngờ là ngay cả trong suốt 3 tháng, một nhà tuyển dụng liên tục hỏi tôi có thể làm việc cho họ hay không. Quả thật, tôi đã không hiểu được: họ có lẽ đã không đọc hồ sơ LinkedIn của tôi? Bởi tôi đã không đi học đại học hoặc có bất cứ bằng cấp gì cao cả.
Và tôi hiểu ra rằng bạn không học cách lập trình ở trường. Bạn học nó bằng cách viết các chương trình và phần mềm. Hầu hết các công ty sẽ không quan tâm nếu bạn có học lập trình ở trường đại học, họ chỉ quan tâm tới kĩ năng cũng như niềm đam mê của bạn.
Đừng hiểu nhầm. Nếu bạn thích cuộc sống ở đại học, hoặc đơn giản là bạn muốn có một số kiến thức cơ bản thì đại học chắc chắn là một quyết định tốt. Tuy nhiên, nó không phải là con đường duy nhất.
Cuộc sống hàng ngày của tôi (ngoài công việc)
Sau khi bootcamp kết thúc, tôi bay về Stockholm. Tôi rất vui mừng khi bắt đầu chương mới này trong cuộc đời, và không thể chờ đợi để tiếp tục phát triển. Vậy hôm nay tôi phải làm gì bây giờ?
Tôi thức dậy và cố gắng thư giản. Chúng thật sự rất quan trọng bởi bạn đã phải ngồi hàng giờ đồng hồ, và cơ thể của bạn chắc chắn sẽ bị tổn thương nếu bạn không chăm sóc nó.
Tôi cố gắng xem các khóa học code trực tuyến ít nhất 2 giờ mỗi ngày. Tôi thích xem chúng bởi vì tôi luôn luôn học những điều mới và lấy cảm hứng từ việc nhìn thấy người hướng dẫn viết code một cách dễ dàng như vậy. Tôi cố gắng tạo ra nét riêng mình bằng cách làm một dự án tương tự ở bên cạnh, hơi khác một chút, vì vậy tôi không chỉ đơn giản sao chép những gì mà người hướng dẫn đang làm.
Tôi cố gắng để làm việc với các dự án cá nhân của mình trong ít nhất 4 giờ. Trong đó, tôi luôn cố gắng sử dụng các ngôn ngữ hoặc kỹ thuật mới lạ để tích lũy kinh nghiệm. Và hãy trung thực, nó có thể sẽ rất khủng khiếp! Tôi sẽ không nói dối và nói rằng nếu bạn làm việc chăm chỉ, bạn sẽ thành công. nhưng tôi cũng thực sự muốn nhấn mạnh vào thực tế là việc học một cái gì đó mới có thể sẽ rất gian khổ thời gian đầu. Bạn sẽ cảm thấy bị mất tinh thần, như rằng bạn sẽ không bao giờ hiểu nócũng như mất tự tin với kỹ năng code của mình. Tuy vậy, việc trải qua những cảm xúc này không quan trọng mà là những gì bạn làm về nó mới là quan trọng nhất. Hãy nghiên cứu nó, viết câu hỏi lên Stack Overflow và chỉ cần tiếp tục cố gắng cho đến khi bạn tìm ra giải pháp.
Tôi cố gắng đọc ít nhất 2 bài báo. Tôi thực sự thích nhìn thấy những điều từ một góc nhìn khác nhau và chúng có thể là về bất cứ điều gì: làm thế nào để giải quyết một vấn đề lập trình nhất định? tại sao đôi khi CSS lại khốn khổ? hay những công nghệ mới tuyệt vời nhất. Điều quan trọng là đừng để mình bị kẹt trong một suy nghĩ lối mòn.
Tôi cố gắng giải quyết ít nhất 5 CodeWars Kata. CodeWars là người bạn thân nhất của bạn khi bạn bắt đầu viết code. Các giải pháp cho những vấn đề họ cung cấp cho bạn thường rất hữu ích bởi bạn sẽ cải thiện được cú pháp của mình rất nhiều bằng cách chỉ cần tham khảo các giải pháp của người khác. Và một điều quan trọng khác nữa: khi bạn đi phỏng vấn, họ sẽ thường cung cấp cho bạn những câu hỏi rất giống với những câu hỏi trên CodeWars!
Tôi cố gắng không ăn đồ ăn vặt và chuyển qua những thực phẩm bổ dưỡng nhằm giữ cho tôi tỉnh táo và vui vẻ hơn! Tôi cũng cảm thấy tràn đầy năng lượng và động lực hơn khi đã có một bữa ăn sáng và trưa lành mạnh. Điều này chắc chắn cải thiện khả năng code của tôi.
Bằng cách viết bài này, tôi hy vọng sẽ truyền cảm hứng cho một số người tham gia vào thế giới công nghệ, và nó thực sự không đáng sợ như nhiều người nghĩ. Lập trình không chỉ dành cho những siêu nhân hoặc các cá nhân siêu phàm như họ miêu tả trong phim. Nghề lập trình luôn dành cho những ai yêu thích việc tạo ra công nghệ, những người yêu thích được thử thách bản thân, và cho bất cứ ai mong muốn cải thiện bản thân mình!
Để kết luận, sau đây là những lời khuyên của tôi:
Bạn thực sự không phải đi học đại học, miễn là bạn có thể thực sự thúc đẩy bản thân và có niềm đam mê cho code!
Luôn luôn 110% sức lực của bạn cho bất cứ khi nào bạn có thể. Tuy nhiên, luôn luôn ưu tiên cho sức khoẻ bản thân. Giấc ngủ là rất quan trọng!
Nó là hoàn toàn bình thường để cảm thấy không thoải mái và nghĩ rằng bạn đang thực sự dở với code nhưng đừng để điều này kéo bạn xuống.
Luôn nhắc nhở bản thân rằng bạn đã đến bao xa. Nó thật sự dễ quên việc bạn đã cải thiện rất nhiều so một tháng trước! Tôi có thể đảm bảo với bạn sẽ ngạc nhiên với những thay đổi từ bản thân.
Đừng để người khác làm cho bạn cảm thấy như ngôn ngữ mà bạn đang học là một ngôn ngữ xấu! Mọi thứ đều có vai trò mà nó tốt nhất, đặc biệt là bạn!
The grouping of two or more database servers is known as database clustering.
Liên kết của hai hoặc nhiều database server thì được hiểu là database clustering
Như đã đề cập ở trên, trường hợp thiết kế Scalable Web Application, rất có thể một hoặc nhiều web service sẽ kết nối chung tới một Database. Cần nhiều web service là do ta cần handle một số lượng lớn request.
Liên kết ở đây được hiểu là dữ liệu ở các cụm Database không hệ khác nhau, được đồng bộ hóa trong quá trình thao tác.
Mô hình Database Clustering. Nguồn ảnh / Source: docs.oracle.com
Cùng có thể hiểu Database Clustering như là cách liên kết. Nhiều các DB liên kết với nhau để tăng cường sức mạnh, đảm bảo ứng dụng hoạt động trơn tru.
Với Database Clustering, có những ưu điểm rõ ràng có thể nhận thấy khi thao tác, bảo trì hệ cơ sở dữ liệu như sau:
2.1 Load Balancing
Bản thân một hệ cơ sở dữ liệu không hề có cơ chế cân bằng tải (Load Balancing) ngay từ ban đầu. Về cơ bản mà nói thì
Basically, what load balancing does is allocating the workload among the different computers that are part of the cluster.
Về cơ bản, những gì cân bằng tải thực hiện là phân bổ khối lượng công việc giữa các máy tính khác nhau là một phần của cluster
Trường hợp số lượng request tăng đột biến, chỉ một services sẽ không thể handle nổi, lúc này sẽ có nhiều web services thực hiện đồng thời, phân bổ và điều tiết số lượng request. Điều này sẽ khả thi với Database Clustering, bởi vì tất cả các web services đó đều sử dụng chung một database
2.2 High Availability
Tính sẵn có cao cũng là một yếu tố để cân nhắc cho việc sử dụng Database Cluster. Sẵn có tức là khi cần truy cập tới database, ta có thể truy xuất được.
High availability refers the amount of time a database is considered available.
Tính sẵn sàng cao đề cập đến khoảng thời gian cơ sở dữ liệu được coi là có sẵn
Trường hợp số lượng request lớn hoặc xử lý ở phía server tương đối phức tạp, rất có thể xảy ra trường hợp các request bị từ chối.
2.3 Data redundancy
Dự phòng dữ liệu cũng là một điểm mạnh khi sử dụng Database Clustering. Do các DB node trong mô hình Clustering được đồng bộ. Trường hợp có sự cố ở một node, vẫn dễ dàng truy cập dữ liệu node khác.
Việc có node thay thế đảm bảo ứng dụng hoạt động mượt mà. Ngay cả khi một hoặc một vài node trong mạng bị down.
3. Khi nào nên sử dụng database clustering?
Ngày nay, các ứng dụng web (web application) thường được yêu cầu hoạt động mượt mà trong tất cả các trường hợp. Vậy khi nào thì cần tới database clustering?
If you’re an entrepreneur, director, or database administrator, you care about database clustering because it helps keep your applications online a greater amount of the time.
Nếu bạn là doanh nhân, giám đốc hoặc quản trị viên cơ sở dữ liệu, bạn quan tâm đến việc phân cụm cơ sở dữ liệu vì nó giúp giữ cho các ứng dụng của bạn trực tuyến trong một khoảng thời gian dài hơn.
Nắm vững khái niệm là một chuyện. Thực tế ở các hệ cơ sở dữ liệu khác nhau sẽ cần tìm hiểu thêm MySQL Cluster CGE
Con đường sự nghiệp của một Product Manager là gì? Nó được đánh giá là rất thú vị với nhiều cung bậc khác nhau từ chuyên môn cho đến cảm xúc. Các yếu tố như quy mô công ty, ngân sách, mục tiêu kinh doanh,… đều sẽ tác động rất nhiều đến cách xây dựng một chiến lược sản phẩm và định hình nên quá trình làm việc của họ cũng như những thành tựu mà họ đạt được.
Lộ trình công việc Product Manager trải qua nhiều giai đoạn khác nhau
Career path của một Product Manager là gì?
Associate Product Manager là gì?
Ở mức độ này, một Product Manager phải chứng minh rằng mình hiểu rõ công việc quản lý sản phẩm là gì và bạn có mối quan tâm cũng như niềm đam mê rõ ràng trong việc làm việc với khách hàng. Điểm dừng đầu tiên này trên con đường sự nghiệp của một Product Manager không giống như khi còn ở trường học. Nó không phải là biết nhiều nhất, làm việc chăm chỉ nhất, hoặc đánh bại đối thủ cạnh tranh. Nó đòi hỏi nhiều yếu tố chuyên môn hơn như thế.
Đó là thể hiện sự đồng cảm của bạn đối với người dùng, làm nổi bật khả năng xác định các vấn đề và cơ hội của bạn cũng như trong việc cộng tác với những người khác. Điều quan trọng là bạn phải chứng tỏ rằng bạn có thể nghe thấy tất cả các khía cạnh của một câu chuyện, tổng hợp và đánh giá mọi thứ và đi đến một quyết định rõ ràng.
Về công việc hàng ngày, một Associate Product Manager tuyển dụng vào công ty sẽ tham gia vào mọi việc mà một Product Manager thường làm, chỉ là ở quy mô và mức độ nhỏ hơn. Nói cách khác, bạn có thể không thiết lập chiến lược sản phẩm nhưng bạn sẽ phải ưu tiên cho các dự án của chính mình. Bạn có thể không trình bày các kế hoạch sản phẩm nhưng bạn sẽ chịu trách nhiệm cập nhật cho các đồng nghiệp và người quản lý của mình.
Product Manager
Đến được với vị trí này đòi hỏi bạn phải là những người đã có kinh nghiệm. Bạn không nhất thiết phải có kinh nghiệm quản lý sản phẩm một cách trực tiếp, nhưng bạn cần phải có một số kinh nghiệm chuyên môn thể hiện rõ ràng như các kỹ năng giao tiếp, làm việc hiệu quả. Mặc dù bạn có thể không cần trải nghiệm sản phẩm thực tế, nhưng chắc chắn bạn sẽ cần phải có hiểu biết về các khái niệm cơ bản và bắt đầu dự án với thái độ hoạt động tích cực.
Để có thể đạt được những bước tiến mới trong sự nghiệp, một Product Manager cần phải tự tin rằng bạn đang làm tốt công việc của mình và được thúc đẩy để giúp team hoàn thành các mục tiêu rộng lớn hơn. Bạn cũng nên có hiểu biết rõ ràng về lợi ích khách hàng mà sản phẩm của bạn cung cấp, có thể trình bày rõ các vấn đề khách hàng cụ thể mà sản phẩm đang giải quyết và có thể gắn các chỉ số sản phẩm với mục tiêu kinh doanh một cách hấp dẫn.
Với vị trí này, có thể nói bạn đã là người có tay nghề “cứng cáp” và có nhiều kinh nghiệm làm việc. Ít nhất một Senior Product Manager thành công sẽ có kinh nghiệm chuyên môn, thể hiện được khả năng tư duy của mình, có trách nhiệm với các quyết định, dẫn dắt và đưa ra các quyết định dựa trên dữ liệu và vô số các yếu tố phức tạp, phụ thuộc lẫn nhau. Vai trò này cũng sẽ đòi hỏi kiến thức sâu về sản phẩm và thị trường.
Senior Product Manager là những người đã có nhiều kinh nghiệm làm việc
Mỗi ngày, Senior Product Manager phải thực hiện hầu hết các nhiệm vụ tương tự như một Product Manager nhưng với các sản phẩm có tác động cao hơn, khả năng hiển thị cũng cao hơn. Họ lãnh đạo các Product Manager cấp dưới khác và làm việc chặt chẽ với các nhà lãnh đạo sản phẩm trong công ty để đóng góp và thực hiện chiến lược sản phẩm. Trong khi các Product Manager khác có thể chú ý đến dữ liệu hoặc tham gia nhiều hơn vào các cuộc phỏng vấn và phản hồi của khách hàng, các Senior Product Manager bắt đầu xem xét nhiều hơn về quy trình sản phẩm rộng hơn và bắt đầu có tiếng nói hơn đối với nhóm sản phẩm.
Vai trò Director of Product yêu cầu kinh nghiệm lãnh đạo và khả năng xây dựng, thể hiện sự tin tưởng một team thực hiện công việc mà bạn đã làm trước đây với tư cách là người đóng góp duy nhất. Vai trò Director of Product cũng sẽ tập trung hơn nữa vào việc xây dựng các quy trình tốt hơn và trau dồi những quy trình hiện có, cải thiện hiệu suất chung của nhóm và xây dựng sự đồng thuận trong toàn bộ tổ chức.
Bạn sẽ thường xuyên gặp gỡ các đồng nghiệp của mình trong toàn công ty, đây là điều đang xảy ra và tại sao, bạn cần gì ở sản phẩm, bạn phải làm gì để sản phẩm tốt hơn,… Công việc này chủ yếu dựa vào dữ liệu. Bạn có một team tập trung vào các KPI riêng lẻ nhưng bạn vẫn sẽ chịu trách nhiệm kết nối những con số quy mô nhỏ đó với các chỉ số thành công rộng hơn của doanh nghiệp nói chung.
Để thành công ở bất cứ công việc nào đều đòi hỏi chúng ta phải đi qua nhiều vị trí, với nhiều thử thách và khó khăn. Nhưng chắc chắn đích đến sẽ là những điều tốt đẹp chờ đợi bạn ở phía trước. Nắm rõ về lộ trình nghề nghiệp của một Product Manager sẽ giúp bạn lên kế hoạch làm việc tốt hơn cho công việc của mình.
Nhà quản trị nhân sự giỏi cần có sự dẫn dắt, truyền đạt tốt cho các nhân viên của mình. Nhiều hệ giá trị được thể hiện như: niềm tin, sự hợp tác, sự dấn thân, tính trách nhiệm với mọi nhiệm vụ. Cùng TopDev điểm qua những phẩm chất mà một nhà nhân sự giỏi nên tạo dấu ấn đối với nhân viên.
Khả năng truyền cảm hứng
Dù doanh nghiệp của bạn có quy mô nhỏ, vừa hay rộng khắp thì không gian văn hóa của doanh nghiệp phải thật sự có ý nghĩa. Vì thế, người lãnh đạo/tuyen dung it cần có một năng lực truyền cảm hứng thông qua “sân nhà”.
Truyền cảm hứng làm một năng lực cần có của nhà lãnh đạo.
Những biểu hiện cụ thể như: tính sáng tạo, chủ động, sự tập trung và chuyên nghiệp trong tác phong nghề nghiệp,…Tất cả đều phản ánh năng lực của mỗi nhà quan trị nhân sự tuyen dung it.
Bạn sẽ là nguồn cảm hứng lớn đối với nhân viên khi tạo cho họ những động lực trên cơ sở các phẩm chất tốt đẹp.
Đồng thời, nhờ sự truyền cảm hứng ấy, nhân viên họ có cách hành xử và nhìn nhận đúng đắn; góc nhìn của họ cũng trở nên đa dạng hơn. Nhờ các động lực, họ có thể phát triển bản thân mình nhiều hơn. Từ đó, lập kế hoạch rèn luyện, trở thành phiên bản tốt hơn mỗi ngày.
Chinh phục sự tử tế
Con người là nổi bật với óc sáng tạo linh hoạt. Không có một giới hạn nào cho các giá trị tốt đẹp mà con người có thể tạo ra. Và sự tử tế cũng vậy. Nó là một phẩm chất tốt mà mỗi nhà tuyen dung it cần gợi nhắc; giúp nó bật lên được trong tính cách mỗi nhân viên. Sự tử tế có thể giúp bạn tiến xa trong nghề nghiệp.
Thiếu đi sự tử tế, sợi dây định hướng về nhân cách cua bạn sẽ có ngày bị biến dạng. Nếu cá nhân người lãnh đạo có sức ảnh hưởng, dùng tiếng nói và cách hành xử của mình để thuyết phục được nhân viên, đó là một dấu hiệu đáng mừng!
Nhiều nhà quản trị nhân sự họ đã quan tâm đến vấn đề này. Đó là lý do tại sao nhân viên họ ngày càng nhiều nhân viên họ quan tâm nhau nhiều hơn. Chính sự tư tế đã giúp họ thay đổi tích cực.
Yêu bản thân
Nếu bạn không biết yêu thương chính mình thì quả thật là một điều đáng tiếc. Mỗi cá nhân nhân sự dù chính thức hay freelancer it đều cần phải biết quan tâm đến chính mình. Đó có thể là về vấn đề sức khỏe, tâm lý, bồi dưỡng tâm hồn,…
Nếu là người đứng đầu tổ chức, bạn không khác gì người anh lớn đang làm gương cho các em mình.
Do vậy, hãy đảm bảo một chế độ luyện tập lành mạnh. Đồng thời, thực hiện một chu trình làm việc gắn liền với những thói quen tốt. Có như vậy, bạn và cả nhân viên sẽ luôn duy trì được nguồn năng lượng tràn đầy trong công việc lẫn cuộc sống cá nhân.
Hãy thật sự quan tâm đến thể trạng của chính bạn. Cả lãnh đạo nhân sự và nhân viên cần rèn luyện hiệu quả. Kết quả công việc quan trọng. Nhưng trạng thái sức khỏe – tinh thần vẫn quan trọng hơn. Chăm sóc tốt nó, bạn sẽ không phải e ngại bất kỳ một thách thức khó khăn nào.
Bài viết được sự cho phép của tác giả Edward Thiên Hoàng
REDUNDANCY
Là phương thức sao lưu các dữ liệu quan trọng của hệ thống với mục đích tăng độ tin cậy (Reliability) của hệ thống. Ví dụ dữ liệu được lưu trên duy nhất một Server, nếu Server đó mất có nghĩa là tất cả dữ liệu đó mất, do đó việc tạo ra các bản sao lưu là để giải quyết vấn đề này. Redundancy là một điều kiện để xóa bỏ những “single points of failure” và tạo ra các bản sao lưu lúc cần thiết, ví dụ ta có hai máy chủ Database đang chạy trên production và dữ liệu luôn được sao lưu đồng bộ giữa hai máy chủ, và nếu có một trong hai máy chủ bị down thì ta có thể failover sang máy chủ còn lại. Redundancy nó giống như duplicate lại node/server dùng cho mục đích back-up vậy.
Gần tương tự với với Redundancy là ta cũng tạo ra một bản sao lưu dữ liệu của Server chính (Master) sang Server backup (Slave), nhưng khác nhau cơ bản là Replication sẽ update dữ liệu giữa Master và Slave là luôn luôn giống nhau và mọi thời điểm (real time synchronization) để tăng độ tin cậy (reliability), đặc biệt là khả năng chịu lỗi của hệ thống (fault-tolerance) và khả năng truy cập (accessibility). Replication được sử dụng rộng rãi ở các CSDLQH (RDBMS) trong mô hình master/slave, dữ liệu giữa master-slave luôn luôn được đồng bộ, trong trường hợp master down thì slave sẽ lên thay master sau khi master vừa down sống dậy nó sẽ trở thành slave mà sẽ thực hiện đồng bộ dữ liệu chưa được update trong thời gian nó bị down.
Một phần quan trọng nhưng thường xuyên bị đánh giá thấp trong việc phát triển phần mềm là Kiểm thử. Kiểm thử, từ trong định nghĩa, đã là một thách thức. Nếu một con bug là dễ dàng tìm thấy, nó sẽ không xuất hiện trên phiên bản đang phát triển, chứ chưa nói đến phiên bản dành cho kiểm thử. Một kỹ sư kiểm thử cần phải think-out-the-box để có thể tìm được những con bug mà người khác bỏ qua. Trong nhiều trường hợp, nắm vững kiển thức nền tảng của hệ thống, cả nghiệp vụ lẫn kỹ thuật, là rất quan trọng cho việc kiểm thử một cách hiệu quả.
Trong các dự án mã nguồn mở, chất lượng sản phẩm được quyết định bởi sự đóng góp và hợp tác giữa nhiều nhà phát triển. Kiểm thử đơn vị, thành phần và dịch vụ thường được làm tự động một cách hiệu quả. Điều này cho phép dự án có thể tiến về phía trước kể cả khi có quá nhiều sự đóng góp. Kiểm thử tự động một cách toàn diện cả chiều rộng và chiều sâu sẽ tăng tính ổn định cho sản phẩm/dự án.
Ngược với dự án mã nguồn mở được xây dựng bằng cách sử dụng sự đóng góp của nhiều người, không có sự liên kết chặt chẽ, mô hình dự án DevOps có thể theo cách tiếp cận Scrum hoặc Kanban mà ở đó, sự phát triển và phát hành sản phẩm là đồng thời và liên tục. Quá trình này phụ thuộc nhiều vào tính toàn diện và liên tục của việc kiểm thử tự động. Bất cứ khi nào có một phiên bản mới (thậm chí là một thay đổi nhỏ trong một tập tin mã nguồn), hệ thống kiểm thử cũng cần kiểm tra rằng hệ thống vẫn hoạt động. Đồng thời, bản thân những mã kiểm thử tự động, kể cả những mã kiểm thử dùng cho kiểm thử giao diện, cũng phải hoạt động chính xác.
Tháp kiểm thử, đề xuất bởi Mike Cohn trong quyển sách của ông, Succedding with Agile, đặt kiểm thử giao diện như là phần nhỏ nhất của quá trình kiểm thử. Hầu hết các kiểm thử nên được tập trung ở mức độ kiểm thử đơn vị và kiểm thử thành phần. Như vậy, việc thiết kế kịch bản kiểm thử dễ dàng hơn, và tự động hóa việc kiểm thử ở mức độ đơn vị hay thành phần/dịch vụ cũng dễ hơn và ổn định hơn.
Tôi đồng ý rằng đây là một chiến lược tốt. Tuy nhiên, từ những gì tôi quan sát được từ nhiều dự án khác nhau, kiểm thử giao diện cũng là một phần quan trọng. Trong thế giới web, ví dụ, các chức năng của các công nghệ như Ajax hay AngularJS cho phép các kỹ sư phát triển tạo ra các trải nghiệm người dùng thú vị và đầy tính tương tác, mà nhiều phần của hệ thống cần phải được kiểm thử chung với nhau. Một ví dụ khác về giao diện là các ứng dụng một trang (single-page application), nơi mà toàn bộ, hay hầu hết, các chức năng của ứng dụng được mang ra cho người dùng ở trên một trang duy nhất. Sự phức tạp của giao diện là một sự thách thức cho kiểm thử tự động hơn hẳn mô hình client-server truyền thống.
Do đó, tôi thích để nhiều không gian kiểm thử ở trên đỉnh hơn, như hình dưới đây:
Ngay cả với kiểm thử giao diện, mặt kỹ thuật cũng khá là đơn giản. Với những công cụ kiểm thử, ví dụ như công cụ mã nguồn mở như Selenium hay công cụ thương mại TestArchitect của chúng tôi, chúng ta có thể tương tác với giao diện, giả lập các hành vi của người dùng trên hệ thống/ứng dụng. Kiểm thử giao diện cũng có thể pha trộn thêm các loại kiểm thử không giao diện khác như kiểm thử dịch vụ API hay truy vấn dữ liệu SQL.
Vấn đề của kiểm thử giao diện xuất hiện chính là ở giao đoạn bảo trì – maintainance. Chỉ một thay đổi nhỏ ỡ giao diện hay hành vi người dùng có thể ảnh hưởng một số lượng lớn số lượng kịch bản kiểm thử tự động tương tác với nó. Lý do cơ bản là thành phần giao diện không còn tồn tại hay những khoảng thời gian chờ đợi không mong muốn để một nghiệp vụ được hoàn thành, những yêu cầu mới để hoàn thành một nghiệp vụ. Việc bỏ qua các lý do đó sẽ làm cho việc tự động hóa khó có thể thành công.
Bài viết được sự cho phép của tác giả Nguyễn Hữu Đồng
Vào một ngày đẹp trời, đang ngồi code lan man mình nhận được thông báo từ xếp, một con service tracking của một project cũ đang gây nghẽn database, chuyện là cty đó đang ăn nên làm ra traffic vô site tăng gấp 15 lần, user tương tác nhiều dẫn đến các con service khác cũng tải nhiều hơn, db thì càng ngày càng bị hấp diêm nhiều hơn, ko chỉ đến từ còn service tracking mà còn đến từ nhiều con khác.
Tracking thì ngàytrước mình code theo mô hình đơn giản, Client gọi API, đẩy message vào 1 cái queue, có tầm 100 con consumer ngồi hốt message ra process rồi ghi vô database.
Nhưng đến nước này thì chỉ có thể giảm tải cho database bằng cách giảm số lượng con consumer xuống, hạn chế tải đồng thời cho database. Trước kia code vô nhân đạo nên mình ko handle chuyện cần restart lại App thì mới update config. Tranh thủ lúc đang nhàn rỗi, mấy dự án đang ngồi chờ chốt requirement nên tranh thủ update sửa cho em nó.
Nhu cầu cần thiết lúc này là
Chỉ cần update file config là app tự động update số consumer
Khi deploy new code thì phải graceful shutdown, chờ mỗi consumer xử lí xong message và cho em nó nghỉ ngơi.
Viper có sẵn tính năng watch config file nên mình sẽ dùng luôn
func watchConsumerCount() {
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
n := viper.GetInt("consumer_count")
if n != consumer_count {
fmt.Println("resize consumer count to => ", n)
go ResizeConsumerCount(n)
}
})
}
Khi config có sự thay đổi thì nếu là thay đổi giá trị số consumer thì mình tiến hành chạy function ResizeConsumerCount để update lại số lượng consumer
Để quản lí mỗi consumer sẽ thì mình có cái slice mỗi phần từ có type như sau
type ConsumerRoutine struct {
Id int // ID của consumer
Exit chan bool // Channel để nhận lệnh exit
Channel *amqp.Channel // AMQP channel
Delivery <-chan amqp.Delivery // AMQP delivery chan,để nhận message từ queue
Done chan bool // Channel báo cáo lên thằng quản lí tao xong hết rồi, chuẩn bị thoát
}
Mỗi consumer khi chạy sẽ ôm cái biến này để giao tiếp với thằng quản lí.
Khởi tạo consumer và các thần phần cần thiết khác.
Bắt đầu tạo consumer, mỗi consumer sẽ được chạy trong 1 goroutine và update tình trạng vào cái biến mà nó đươc giao
func startNewConsumer(m *ConsumerRoutine) {
m.Exit = make(chan bool)
m.Done = make(chan bool)
m.Channel, _ = amql_conn.Channel()
m.Channel.QueueDeclare(queue_name, true, false, false, false, nil)
m.Delivery, _ = m.Channel.Consume(queue_name, "", false, false, false, false, nil)
fmt.Println("Consumer : ", m.Id, "started")
for {
select {
case <-m.Exit: // Lắng nghe lệnh exit từ bên ngoài
m.Channel.Close() // Đóng amqp channel
m.Channel = nil
m.Done <- true // Báo cáo là sẵn sàng thoát
fmt.Println("Consumer ", m.Id, " ended")
return
case msg := <-m.Delivery: // Chờ message từ queue
// Xử lí message ở đây
fmt.Println("Consumer ", m.Id, "recived message = ", string(msg.Body))
// Ack hoặc Reject message, ở đây để luôn có data test nên mình reject luôn :pikatroll:
msg.Reject(true)
}
}
}
Mỗi khi chạy một con consumer mới thì nó sẽ lắng nghe lệnh exit từ bên ngoài thông qua channel m.Exit , nhận message từ queue qua channel m.Delivery . Có message thì sẽ xử lí khi nào xong thì nghe tiếp.
Đến lượt function thay đổi số lượng consumer
func ResizeConsumerCount(n int) {
// scale up
// Chỗ này thì thêm phần từ vô slice và sau đó thì chạy một con
// consumer và truyền biến vào để giao tiếp
if n >= consumer_count {
val := consumer_count
consumer_count = n
for i := val; i < n; i++ {
consumer[i] = &ConsumerRoutine{
Id: i,
Exit: make(chan bool),
Done: make(chan bool),
}
go startNewConsumer(consumer[i])
}
return
}
// scale down
// Giả sự số lượng hiện tại là consumer_count
// và số consumer sau khi giảm là n thì mình sẽ
// gửi lệnh exit cho những con consumer từ n->val-1
// vì slice được đếm từ 0
val := consumer_count
consumer_count = n
for i := n; i < val; i++ {
fmt.Println("shuting down consumer : ", i)
go func(m *ConsumerRoutine) {
fmt.Println("Exit Chan Pointer = ", &m.Exit)
m.Exit <- true
}(consumer[i])
<-consumer[i].Done
}
}
Và function main nơi mà mọi thứ bắt đầu.
func main() {
// Mình chạy consumer_count con consumer từ file config
for i := 0; i < consumer_count; i++ {
consumer[i] = &ConsumerRoutine{
Id: i,
}
go startNewConsumer(consumer[i])
}
// khởi tạo 1 channel để lắng nghe signal
stop := make(chan os.Signal, 1)
signal.Notify(stop)
for {
v := <-stop
fmt.Println("SIGNAL : ", v.String())
// nếu signal là hangup thì mình sẽ tắt hết consumer và thoát app
if v.String() == "hangup" {
ResizeConsumerCount(0)
os.Exit(0)
}
}
}
➜ resizeConsumer go build && ./rc
Consumer : 0 started Exit pointer val = 0xc00019a018
Consumer : 1 started Exit pointer val = 0xc00019a058
SIGNAL : urgent I/O condition
SIGNAL : urgent I/O condition
SIGNAL : urgent I/O condition
SIGNAL : urgent I/O condition
SIGNAL : urgent I/O condition
Config file changed: /Users/vimftw/Desktop/code/resizeConsumer/config.yaml
resize consumer count to => 1
shuting down consumer : 1
Exit Chan Pointer = 0xc00019a058
have to exit now
Consumer 1 ended
shuting down consumer : 2
Exit Chan Pointer = 0xc00005a718
have to exit now
Consumer 2 ended
shuting down consumer : 3
Exit Chan Pointer = 0xc00005a758
have to exit now
Consumer 3 ended
SIGNAL : urgent I/O condition
SIGNAL : urgent I/O condition
Thử tắt luôn con app
SIGNAL : urgent I/O condition
SIGNAL : urgent I/O condition
SIGNAL : hangup
shuting down consumer : 0
Exit Chan Pointer = 0xc00019a018
have to exit now
Consumer 0 ended
Bài viết được sự cho phép của tác giả Kien Dang Chung
Hiện nay, thương mại điện tử đang đạt đến đỉnh cao, rất nhiều các chương trình được đưa ra nhằm tăng doanh số bán hàng, quảng bá sản phẩm mạnh mẽ hơn. Một trong những cách thức đó là các chương trình giới thiệu bán hàng (referral system), nó giống như mô hình truyền thống trong việc mở rộng các đại lý phân phối sản phẩm, tuy nhiên có một điểm khác biệt là các đại lý truyền thống cần có sản phẩm để bán thì với chương trình này, đại lý chỉ việc giới thiệu các sản phẩm, dựa trên uy tín của mình, đại lý có thể giới thiệu được nhiều sản phẩm và có thu nhập tốt.
Các chương trình giới thiệu bán hàng đã tận dụng được lợi thế về quảng bá trên Internet giúp bạn nhanh chóng mở rộng được đại lý bán hàng, tuy nhiên bạn cũng phải thường xuyên tạo ra các chương trình chia sẻ lợi nhuận hấp dẫn, thiết kế các mẫu quảng bá thu hút người xem (hoặc do các đại lý thiết kế) và quan trọng hơn nữa là thường xuyên tạo ra các chương trình chi ân nhằm giữ chân khách hàng lâu dài. Như vậy, có thể thấy Referral là hệ thống quan trọng đối với một website bán hàng, với các website khác áp dụng hệ thống referral cũng là cách tốt để có được lượng traffict lớn ngoài các thành viên thường xuyên.
Trong mô hình trên, bạn có thể thấy tất cả các đối tượng tham gia đều được hưởng lợi:
Người giới thiệu (hay còn gọi là đại lý): sẽ nhận được hoa hồng khi giao dịch thành công.
Người được mời (người mua): nhận được các chương trình giảm giá, chương trình chi ân khách hàng từ hệ thống. Các hệ thống bán hàng có thể giảm giá tốt hơn với các khách hàng tiềm năng này.
Nhà phân phối (có hệ thống giới thiệu bán hàng – referral system): tăng doanh số bán hàng, tiếp cận được nhiều khách hàng tiềm năng.
Xây dựng hệ thống giới thiệu bán hàng – referral system trong ứng dụng Laravel
Bước 1: Tạo các bảng liên quan trong CSDL
Chúng ta sẽ tạo ra hai bảng referral_programs và referral_links:
c:\xampp\htdocs\laravel-test>php artisan make:migration create_referral_programs_table --create=referral_programs
Created Migration: 2017_04_24_075438_create_referral_programs_table
c:\xampp\htdocs\laravel-test>php artisan make:migration create_referral_links_table --create=referral_links
Created Migration: 2017_04_24_075503_create_referral_links_table
c:\xampp\htdocs\laravel-test>php artisan make:migration create_referral_relationships_table --create=referral_relationships
Created Migration: 2017_04_24_081042_create_referral_relationships_table
Thêm nội dung tạo các bảng liên quan, với file 2017_04_24_075438_create_referral_programs_table:
<?phpuseIlluminate\Support\Facades\Schema;useIlluminate\Database\Schema\Blueprint;useIlluminate\Database\Migrations\Migration;classCreateReferralProgramsTableextendsMigration{/**
* Run the migrations.
*
* @return void
*/publicfunctionup(){Schema::create('referral_programs',function(Blueprint $table){$table->increments('id');$table->string('name');$table->string('uri');$table->integer('lifetime_minutes')->default(7*24*60);$table->timestamps();});}/**
* Reverse the migrations.
*
* @return void
*/publicfunctiondown(){Schema::dropIfExists('referral_programs');}}
Với file 2017_04_24_075503_create_referral_links_table:
<?phpuseIlluminate\Support\Facades\Schema;useIlluminate\Database\Schema\Blueprint;useIlluminate\Database\Migrations\Migration;classCreateReferralLinksTableextendsMigration{/**
* Run the migrations.
*
* @return void
*/publicfunctionup(){Schema::create('referral_links',function(Blueprint $table){$table->increments('id');$table->integer('user_id')->unsigned();$table->integer('referral_program_id')->unsigned();$table->string('code',36)->index();$table->unique(['referral_program_id','user_id']);$table->timestamps();});}/**
* Reverse the migrations.
*
* @return void
*/publicfunctiondown(){Schema::dropIfExists('referral_links');}}
Thêm nội dung tạo referral_relationships:
<?phpuseIlluminate\Support\Facades\Schema;useIlluminate\Database\Schema\Blueprint;useIlluminate\Database\Migrations\Migration;classCreateReferralRelationshipsTableextendsMigration{/**
* Run the migrations.
*
* @return void
*/publicfunctionup(){Schema::create('referral_relationships',function(Blueprint $table){$table->increments('id');$table->integer('referral_link_id');$table->integer('user_id');$table->timestamps();});}/**
* Reverse the migrations.
*
* @return void
*/publicfunctiondown(){Schema::dropIfExists('referral_relationships');}}
Tiếp theo thực hiện tạo hai bảng này bằng lệnh php artisan migrate
Sử dụng câu lệnh artisan make:model để tạo ba model là ReferralProgram, ReferralLink và ReferralRelationship
c:\xampp\htdocs\laravel-test>php artisan make:model ReferralProgram
Model created successfully.
c:\xampp\htdocs\laravel-test>php artisan make:model ReferralLink
Model created successfully.
c:\xampp\htdocs\laravel-test>php artisan make:model ReferralRelationship
Model created successfully.
Trong project này chúng ta sẽ sử dụng package ramsey/uuid là một thư viện làm việc với Universally Unique Identifiers (UUID) tương thích với tiêu chuẩn RFC 4122 phiên bản 1, 3, 4 và 5. Thực hiện cài đặt vào dự án bằng lệnh composer.
c:\xampp\htdocs\laravel-test>composer require ramsey/uuid
Using version ^3.6for ramsey/uuid
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations:0 installs,1 update,0 removals
- Updating ramsey/uuid (3.6.0=>3.6.1): Loading from cache
Writing lock file
Generating autoload files
>Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized classloader
The compiled services file has been removed.
Ngoài ra chúng ta cần cài đặt thêm gói moontoast/math được sử dụng trong các thuật toán của ramsey/uuid:
c:\xampp\htdocs\laravel-test>composer require moontoast/math
Using version ^1.1for moontoast/math
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations:1 install,0 updates,0 removals
- Installing moontoast/math (1.1.2): Downloading (100%)
Writing lock file
Generating autoload files
>Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized classloader
The compiled services file has been removed.
<?phpnamespaceApp;useIlluminate\Database\Eloquent\Model;useRamsey\Uuid\Uuid;classReferralLinkextendsModel{protected$fillable=['user_id','referral_program_id'];protectedstaticfunctionboot(){static::creating(function(ReferralLink $model){$model->generateCode();});}privatefunctiongenerateCode(){$this->code=(string)Uuid::uuid1();}publicstaticfunctiongetReferral($user,$program){returnstatic::firstOrCreate(['user_id'=>$user->id,'referral_program_id'=>$program->id]);}publicfunctiongetLinkAttribute(){returnurl($this->program->uri).'?ref='.$this->code;}publicfunctionuser(){return$this->belongsTo(User::class);}publicfunctionprogram(){ // TODO: Check if second argument is requried
return$this->belongsTo(ReferralProgram::class,'referral_program_id');}publicfunctionrelationships(){return$this->hasMany(ReferralRelationship::class);}}
Tiếp theo chúng ta cần giám sát các đường link có tham số ref và lưu chúng vào cookie, như vậy mỗi khi có một hành động nào đó của người dùng chúng ta có thể biết và tặng quà cho cả hai bên tham gia. Để thực hiện được việc này chúng ta tạo ra một middleware (Xem thêm Laravel middleware).
c:\xampp\htdocs\laravel-test>php artisan make:middleware StoreReferralCode
Middleware created successfully.
và thay đổi nội dung app\Middlewares\StoreReferralCode.php như sau:
Phương thức handle() của middleware StoreReferralCode sẽ thực hiện kiểm tra tất cả các request nếu có tham số ref sẽ tìm kiếm
Bước 4: Tạo Event và Listener quản lý các hành động người dùng
Khi hành động như mong muốn được người dùng thực hiện (ở đây là đăng ký tài khoản mới), chúng ta thực hiện tạo ra một event và dùng listener để bắt sự kiện đó, trong listener sẽ thực hiện tặng thưởng cho người dùng. Thêm cấu hình vào EventServiceProvider.php trong thư mục app\Providers:
Sau đó sử dụng lệnh artisan event:generate để tự động tạo ra Event và Listener (Xem thêm Quản lý sự kiện với Laravel Event để hiểu hơn về câu lệnh này):
c:\xampp\htdocs\laravel-test>php artisan event:generate
Events and listeners generated successfully!
Thay đổi nội dung của Event app\Events\UserReferred.php:
<?phpnamespaceApp\Events;useIlluminate\Broadcasting\Channel;useIlluminate\Queue\SerializesModels;useIlluminate\Broadcasting\PrivateChannel;useIlluminate\Broadcasting\PresenceChannel;useIlluminate\Foundation\Events\Dispatchable;useIlluminate\Broadcasting\InteractsWithSockets;useIlluminate\Contracts\Broadcasting\ShouldBroadcast;classUserReferred{useDispatchable, InteractsWithSockets, SerializesModels;public$referralId;public$user;/**
* Create a new event instance.
*
* @return void
*/publicfunction__construct($referralId,$user){$this->referralId=$referralId;$this->user=$user;}/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/publicfunctionbroadcastOn(){returnnewPrivateChannel('channel-name');}}
Thêm nội dung của app\Listener\RewardUser.php:
<?phpnamespaceApp\Listeners;useApp\Events\UserReferred;useIlluminate\Queue\InteractsWithQueue;useIlluminate\Contracts\Queue\ShouldQueue;classRewardUser{/**
* Create the event listener.
*
* @return void
*/publicfunction__construct(){ //
}/**
* Handle the event.
*
* @param UserReferred $event
* @return void
*/publicfunctionhandle(UserReferred $event){$referral= \App\ReferralLink::find($event->referralId);if(!is_null($referral)){
\App\ReferralRelationship::create(['referral_link_id'=>$referral->id,'user_id'=>$event->user->id]); // Tặng thưởng cho cả người share link và người sử dụng link
if($referral->program->name==='Bonus Credits'){ // Người chia sẻ link
$provider=$referral->user;$provider->addCredits(15); // Người sử dụng link
$user=$event->user;$user->addCredits(20);}}}}
Ok, tiếp theo chúng ta sẽ tạo ra một event app\Events\UserReferred.php khi người dùng đăng ký bằng cách can thiệp vào phương thức create() của RegisterController.php nằm trong app\Http\Controllers\Auth:
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/protectedfunctioncreate(array$data){$user=User::create(['name'=>$data['name'],'email'=>$data['email'],'password'=>bcrypt($data['password'])]);event(new\App\Events\UserReferred(request()->cookie('ref'),$user));return$user;}
Tạo view referral.blade.php trong resources/views/fontend:
@extends('layouts.default')
@section('title','Referral system - Allaravel.com')
@section('content')
@forelse(auth()->user()->getReferrals()as$referral)<h4>
Chương trình:{{$referral->program->name}}</h4><code>
Referral link:{{$referral->link}}</code><p>
Số user sử dụng referral link:{{$referral->relationships()->count()}}</p>
@empty
Không có chương trình referral nào!
@endforelse
@endsection
Thêm menu Referral System vào resources/views/layouts/menu.php:
Trước khi đi vào kiểm tra hoạt động hệ thống referral, chúng ta cùng xem qua luồng hoạt động của nó.
Các bước thực hiện kiểm thử cũng sẽ tuân thủ theo hoạt động mô tả ở luồng hoạt động hệ thống ở trên: Đầu tiên, đăng nhập vào hệ thống laravel.dev tại http://laravel.dev/login, sau khi đăng nhập chuyển sang menu Ví dụ->Referral System. Nhưng trước tiên chúng ta cần tạo ra một chương trình giới thiệu bán hàng trước đã do hiện tại bảng referral_programs đang chưa có bản ghi nào. Sử dụng Laravel Tinker để nhập nhanh một bảng ghi (Nếu bạn chưa biết Tinker là gì xem thêm Công cụ debug và kiểm thử trong Laravel):
Như vậy, thành viên này đã có referral link, thành viên này muốn kiếm tiền có thể đưa đường dẫn này vào bất kỳ đâu: – Mạng xã hội Facebook, Google Plus, Twitter, Github…
Website: Blog, trang tin tức…
Email: Gửi email trong nội dung có đường dẫn này.
…
Bất kỳ ai khi thực hiện click vào đường dẫn này, hệ thống sẽ ghi xuống máy tính của họ một cookie chứa id bản ghi trong referral_links, cookie này có thời gian hoạt động mặc định là 7 ngày, do trong phần tạo bảng referral_programs chúng ta để là:
Trong khoảng thời gian này, nếu người dùng trên thực hiện đăng ký tài khoản, referral system sẽ biết do đã cài đặt các Event và Listener. Khi đó tùy thuộc vào chương trình giới thiệu bán hàng chúng ta sẽ xử lý trả thưởng cho cả người chia sẻ link và người dùng link trong phương thức hanlde() của Listener.
/**
* Handle the event.
*
* @param UserReferred $event
* @return void
*/publicfunctionhandle(UserReferred $event){$referral= \App\ReferralLink::find($event->referralId);if(!is_null($referral)){
\App\ReferralRelationship::create(['referral_link_id'=>$referral->id,'user_id'=>$event->user->id]); // Tặng thưởng cho cả người share link và người sử dụng link
if($referral->program->name==='Bonus Credits'){ // Người chia sẻ link
$provider=$referral->user;$provider->addCredits(15); // Người sử dụng link
$user=$event->user;$user->addCredits(20);}}}
Để kiểm tra các công đoạn này, chúng ta mở một trình duyệt khác và dán vào đường dẫn referral ở trên (Trong bài viết này, người chia sẻ link dùng Chrome, người dùng link sử dụng Firefox):
Khi thực hiện đăng ký xong, quay trở lại với người chia sẻ link chúng ta sẽ thấy số lượng người sử dụng link tăng lên:
Ok, như vậy referral system của chúng ta đã hoạt động tốt. Với khung ứng dụng này, chúng ta hoàn toàn có thể thực hiện các hệ thống referral với các sự kiện phức tạp hơn.
Chắc hẳn ai trong chúng ta cũng đều mong muốn trải nghiệm tại các công ty có môi trường thoải mái. Đơn giản vì đó là môi trường tốt bạn học hỏi nhiều hơn. Khi tuyen dung it da nang, nhiều ứng viên cũng quan tâm đến vấn đề này. Tuy nhiên, bạn nên cẩn trọng trước những phát ngôn để không vạ miệng trước cấp trên của bạn. Và điều đó cũng cho thấy kỹ năng giao tiếp rất quan trọng. Cùng TopDev khám phá xem đâu là 5 phát ngôn cần tránh nhé!
1. “Tôi bắt đầu hơi chán vì quá tải”
Áp lực công việc là điều hiển nhiên tồn tại khi bạn quyết định đồng hành cùng công việc nào đó một cách lâu dài. Áp lực đôi khi làm bạn mệt mỏi. Thế nhưng, thực tếchính nó tạo nên động lực giúp bạn khám phá ra được giới hạn về năng lực của chính mình.
Một điều quan trọng nữa, môi trường văn phòng là nơi làm việc chứ không phải nơi bạn kêu ca.
Mọi thứ cần phải chuyên nghiệp và tuân thủ theo nguyên tắc. Nếu công việc quá tải, bạn nên xem xét lại các đầu công việc; sắp xếp theo thứ tự; cân bằng lại thời gian biểu của mình.
Đừng mãi phàn nàn và đổ lỗi cho hoàn cảnh! Cũng đừng biện hộ vì điều đó sẽ khiến người khác đánh giá thấp bạn. Thay vì phát ngôn như vậy, bạn nên tự nỗ lực giải quyết nó.
Hãy suy nghĩ đơn giản hơn, xem những áp lực như một thách thức mà bạn cần phải vượt qua; cố gắng tìm ra giải pháp hoặc đề xuất những cải tiến công việc để nhận lời khuyên và sự hỗ trợ từ người quản lý. Khi tuyen dung it da nang, bạn nên lường trước những vấn đề này chuẩn bị tinh thần cho nó.
2. “Nếu không tăng lương, tôi sẽ nghỉ việc”
Cách bạn nói như vậy không tạo ra sự đe dọa với sếp dù bạn nghĩ rằng nó sẽ thành công. Phát ngôn ấy có thể khiến bạn bị loại khỏi cuộc chơi nghề nghiệp.
Trong tuyen dung it da nang, freelancer it, việc tuyển dụng và đánh giá lại quá trình làm việc của bạn sẽ được diễn ra định kỳ. Thậm chí còn rất cạnh tranh. Thế nên, dù bạn có “ngỏ ý” muốn nghỉ việc trong bất kỳ trường hợp, công ty sẽ không e ngại điều gì mà có thể từ chối bạn ngay lập tức. Và tất nhiên, một lá đơn xin nghỉ việc không cần phải xảy ra nữa. Bởi lẽ, cuộc chơi nghề nghiệp không dành cho những kẻ chỉ biết cho bản thân.
3. “Chúng tôi đã luôn xử lý vấn đề theo cách này…”
Bản thân mọi nhà tuyen dung it da nang rất khuyến khích và mong muốn nhân viên của mình tham gia vào cuộc đối thoại cởi mở. Lúc đó họ có thể đưa ra những ý tưởng hay. Tuy nhiên, câu nói “chúng tôi đã luôn xử lý vấn đề theo cách này…” là điều không một người đứng đầu doanh nghiệp hay tổ chức nào muốn nghe cả. Bạn phải luôn lưu tâm kỹ năng giao tiếp thật sự cần thiết.
Thật ra, phát ngôn này đôi khi bắt nguồn từ cá tính nhân viên; từ năng lực biểu lộ sự tự tin và niềm tin về năng lực kỹ năng giao tiếp bản thân. Tuy nhiên, điều này dường như trái ngược với các giá trị cốt lõi về trách nhiệm, sự minh bạch, văn hóa làm việc chung tại tổ chức.
4. “Tôi không muốn làm việc cùng anh A/chị B/bạn C”
Những mâu thuẫn cá nhân là điều khó tránh khỏi ở môi trường công sở.
Điều quan trọng là làm thế nào để giải quyết chúng để có được tiếng nói chung. Sẽ là một sai lầm lớn nếu bạn than vãn điều này với sếp của mình. Bạn cần biết rằng, để có thể phát triển xa hơn trong nghề nghiệp bạn cần phải làm việc; trao đổi với nhiều đồng đội khác nhau.
Không một người thành công nào lại không biết cách giải quyết xung đột. Vì vậy, nếu có bị “đánh bay” khỏi công việc, bạn cũng đừng thắc mắc vì khả năng nghề nghiệp của bạn thật sự chưa toàn diện.
Điều quan trọng là bạn phải cố gắng hoặc tập cách làm việc theo nhóm để đáp ứng được nhu cầu công việc. Bạn không nên vội từ bỏ khi đã quá quen làm việc độc lập. Nếu có khó khăn với đồng nghiệp, bạn nên chia sẻ với sếp. Cụ thể đó là mong muốn của bản thân. Đừng để những đánh giá cảm tính, chủ quan của bạn làm ảnh hưởng đến sự nghiệp của bạn.
5. “Đó không phải việc của tôi”
Phát ngôn này được cho là tạo ra sự khó xử với chính người cấp trên của bạn.
Ngay cả khi đó không phải công việc của bạn, nhà quản lý không bao giờ muốn nghe bạn thẳng thắn từ chối. Bạn có thể kiệt sức vì quá tải công việc, nhưng điều đó là không thể chấp nhận được ở góc độ nhà quản lý. Nghe có vẻ khó khăn, nhưng điều đó thể hiện sự thiếu chuyên nghiệp và tinh thần không hợp tác trong công việc.
Rõ ràng, bạn hoàn toàn có thể lựa chọn một cách trả lời khôn ngoan hơn. Vậy tại sao bạn lại không thử?
Khi được hỏi một công việc không liên quan đến bạn, hãy giữ thái độ cởi mở. Nhà quản lý sẽ rất vui khi thấy một tập thể cân bằng và hỗ trợ lẫn nhau. Do đó, hãy thể hiện rằng bạn sẵn sàng giúp đỡ họ bất cứ lúc nào.
Lời kết
Ranh giới giữa người quản lý và nhân sự luôn tồn tại. Nhưng chẳng có sếp nào muốn xa lánh nhân viên mà không có lý do cả. Vì thế, hãy cẩn trọng và tinh hết trong mọi phát ngôn. Hãy là một nhân viên chuyên nghiệp nhất trong kỹ năng giao tiếp của mình.
Bài viết được sự cho phép của tác giả Edward Thiên Hoàng
Proxy server là một server trung gian (intermediary) nằm giữa client và back-end server. Client kết nối với proxy server để yêu cầu (request) những dịch vụ (service) cần thiết như API, web page, file hay connection, v.V… Nói tóm lại, proxy server là một phần của hệ thống phần mềm hoặc phần cứng đóng vai trò trung gian kết nối các yêu cầu từ client tới các thành phần khác trong hệ thống.
Proxy được sử dụng chủ yếu để lọc hoặc ghi log các yêu cầu (filter request, log request) hoặc để thay đổi các request (như thêm hoặc xóa các header, mã hóa/giải mã hay nén các resource). Hoặc một ứng dụng rất hữu ích khác là dùng để cache response rồi trả về cho nhiều request cùng loại, như trong trường hợp nhiều client request tới cùng một resource thì Proxy có thể cache resource đó rồi trả về cho các client mà không cần gọi tới các “remote server” khác.
Mô hình Proxy Server hoạt động
CÁC KIỂU PROXY SERVER
Open Proxy
Một Open Proxy Server là một máy chủ mà bất kỳ người dùng Internet nào cũng có thể truy cập. Thông thường nó thường được sử dụng để kiểm xoát băng thông hoặc lưu và chuyển tiếp các dịch vụ mạng như DNS hoặc các dịch vụ Web của một nhóm người dùng sử dụng chung Open Proxy đó. Có hai loại Open Proxy là
+ Proxy ẩn danh (Anonymous Proxy): Proxy server này có thể che dấu các IP thật của các user sử dụng nó khỏi các dịch vụ nó truy cập đến. Proxy ẩn danh có tác dụng tăng độ bảo mật cho người dùng vì địa chỉ IP thực của người dùng có thể được sử dụng để truy dẫn ra thông tin về người dùng và để thâm nhập vào máy tính của người đó. Hoặc dùng để vượt qua tường lửa của các tổ chức hoặc quốc gia Ngoài ra, proxy ẩn danh còn được dùng để lách qua sự kiểm duyệt Internet của các chính phủ hoặc tổ chức.
+ Proxy minh bạch (Trаnspаrent Proxy): Trái ngược với anonymous Proxy, thì proxy này cho phép các dịch vụ truy cập tới biết được IP thật của user bằng các HTTP header (ví dụ như X-Forwarded-For). Ưu điểm của Proxy này là khả năng cache response như website để tăng tốc độ kết nối mạng của những người dùng bên trong máy chủ Proxy.
Reverse Proxy
Reverse proxy là một proxy server mà khi đứng trước client, có tác dụng chuyển tiếp request đến một hoặc nhiều back-end server và nhận kết quả từ các server này rồi trả về phía client (forwarder), giúp che dấu danh tính của các back-end server bên dưới. Reverse proxy được cài đặt trong một private network của một hoặc nhiều server, và tất cả lưu lượng truy cập đều phải đi qua proxy này.
Thông thường, những server sẽ sử dụng cơ chế reverse proxy này để bảo vệ các ứng dụng có khả năng xử lý HTTP yếu kém hơn. Ví dụ như khả năng xử lý cực lớn các request, những hạn chế về xử lý sự đa dạng của các loại request (các dạng request có thể kể đến như: HTTP(S) 1.x, HTTP(S) 2.x, …) hay khả năng chuyển đổi HTTPS thành HTTP, cache request, xử lý dữ liệu của cookies/session, chia một request thành nhiều request nhỏ hơn rồi tổng hợp lại các response, …
Vì các task cần estimate thường là những task mới, mơ-hồ và có nhiều yếu tố không-xác-định xuất hiện trong suốt quá trình thực hiện. Tôi cảm thấy estimate giống như việc dự đoán tương lai, phải may mắn lắm mới có một kết quả chính xác. Việc này tương tự như trò ném phi tiêu trúng hồng tâm vậy… xác suất trúng là rất thấp! Tôi không thích suy nghĩ này. Để tránh những tổn thất sau mỗi lần release muộn, tôi bắt đầu tìm kiếm những đội khác cũng gặp phải vấn đề tương tự, tổng kết lại các phương pháp xử lý và lấy ra các giải pháp hiệu quả nhất.
Và đây là giải pháp mà anh em tổng kết lại “Sau khi estimate thời gian để hoàn thành một tính năng X, hãy x3 con số này lên. 😅”
Hiển nhiên, đây không phải là công thức estimate chính xác.
Trong quá trình tìm kiếm giải pháp cho vấn đề này, tôi đã học được một thứ đó là không hề có mẹo hay lối tắt để giải quyết vấn đề. Chúng ta cần thực hiện đầy đủ tuần tự các bước để có kết quả estimate chuẩn nhất.
Dưới đây là 4 bước mà tôi đã sử dụng để estimate cho các dự án của mình
Bước 1. Phân bổ thời gian dành cho việc estimate
Nếu bạn thực sự muốn đội của mình có thể đưa ra estimate chính xác nhất, cố gắng đừng bắt đầu câu chuyện bằng những câu kiểu như “tôi cần bạn hoàn thành toàn bộ các đầu việc này trước thời điểm X”.
Đưa ra thời điểm cần hoàn thành trước, rồi mới yêu cầu anh em estimate sẽ khiến cho việc estimate không còn đúng với lẽ tự nhiên. Kéo theo kết quả estimate sẽ không gần với thực tế.
Khi anh em dev bị giới hạn thời điểm deadline và liên tục bị giục hoàn thành việc estimate, mọi người sẽ khó có thể nhìn nhận các yếu tố phức tạp của bài toán để estimate, và sẽ estimate theo kiểu cố gắng làm hài lòng người quản lý là chính.
Do vậy, tốt hơn hơn là cho phép cả team một khoảng thời gian, tùy vào khối lượng của project để nhận ra được các vấn đề phức tạp tiềm ẩn và không đề cập tới hạn deadline của các tính năng trước khi estimate.
Việc này để để sau khi estimate xong, để quyết định xem có nên xóa một phải chức năng phức tạp quá hay không.
Bước 2. Chia nhỏ công việc thành các công việc con
Thông thường vào thời điểm bắt đầu dự án, bạn không có đủ thông tin chi tiết về tính năng phải làm. Do vậy, số ngày mà bạn estimate được thường không phản ánh đúng số ngày thực tế.
Tuy nhiên, nếu bạn chia nhỏ công việc cần estimate thành những công việc nhỏ hơn, bạn sẽ có khả năng nhìn thấy được cụ thể những bước cần phải. Do vậy, bạn sẽ estimate được chính xác hơn.
“Khi bạn còn chưa biết được cụ thể bạn sẽ làm những gì, bạn sẽ không thể biết khi nào bạn sẽ hoàn thành nó” –Joel Spolsky, Stack Overflow CEO
Nguyên tắc ở đây là bạn cứ tiếp tục chia nhỏ task cho đến khi thời gian estimate hoàn thành mỗi task nhỏ là từ 8-10h.
Bước 3. Phân loại task
Sau khi chia nhỏ công việc thành những công việc nhỏ hơn, bạn cần lùi lại một chút để nhìn được tổng thể những công việc sẽ phải làm. Bạn sẽ để ý thấy được có vô vàn những việc bạn có thể bắt tay vào làm luôn, một vài việc vẫn còn lờ mờ, và một vài việc vẫn có nhiều điều bí ẩn như là vùng tối phía bên kia của mặt trăng.
Cụ thể hơn, chúng ta có 3 loại công việc sau:
Task đã rõ những việc phải làm (Known Tasks)
Đây là những task mà bạn đã biết rõ input, output và cụ thể các bước cần phải làm để có được output. Do vậy thời gian estimate để hoàn thành công việc này là xác định.
Task mới chỉ rõ một phần những việc phải làm (Partially Known Tasks)
Đây là loại task mà bạn mới chỉ nắm được input, output và nắm được sơ bộ cách làm. Tuy nhiên bạn ước lượng sẽ mất chừng 15-30 phút để tìm hiểu thêm hoặc cần thêm sự trợ giúp từ những người đã gặp vấn đề tương tự để có thể hoàn thành được task.
Task không xác định (Unknown Tasks)
Thường những task này sẽ cần bạn dành khoảng vài giờ tới cả ngày để hiểu công nghệ mà bạn sẽ định sử dụng để hoàn thành task.
Hiếm có dự án nào mà DEV không cần phải học thêm một cái gì đó mới để có thể làm được. Việc phải học thêm các công nghệ mới để hoàn thành dự án là không thể tránh khỏi. Thông thường bạn sẽ cần phải tìm những công cụ, nền tảng API khác khau để giải quyết các bài toán. Do vậy, thời gian dành cho việc tìm hiểu hay nghiên cứu là yếu tố quan trọng cần phải được tính vào estimate.
Sau khi phân loại task, bạn cần cố gắng đặt mục tiêu tìm hiểu thêm về project để cố gắng chuyển task Partially Known Tasks và Unknown Tasks về loại Known Tasks
Bước 4. Estimate lại
Tới bước này, tất cả các task của bạn đã được chuyển thành Known Task, bạn đã có thêm nhiều thông tin cụ thể hơn cho công đoạn implement. Do vậy, kéo theo là kết quả estimate sẽ chính xác hơn.
Hãy quan sát biểu đồ sau để thấy được sự liên hệ giữa thời gian estimate và mức độ rõ ràng của các yêu cầu cũng như các giải pháp để thực hiện các yêu cầu.
Một ưu điểm của bước này là bạn có cơ hội xem lại các yêu cầu, có cái nhìn tổng quan hơn. Và sẽ có thể phát hiện ra những vấn đề mà ở các bước trước bạn chưa kịp nhìn ra. Một điểm chú ý ở đây là, mỗi khi bạn có thêm thông tin gì mới về project, bạn nên estimate lại để có con số chính xác nhất.
Hãy chú ý 4 thứ sau trong khi bạn đang estimate project
Điều 1. Lưu ý những câu có từ “Chỉ” – “Just”
Có một luật bất thành văn là thường những task có nhiệm vụ “Chỉ” làm một tính năng nào đó lại là những task tốn kém nhất.
Task này chỉ nhỏ như con muỗi ấy mà!
Chắc chỉ mất 5 phút để fix lỗi thôi
Chắc task này không chiếm quá 15 phút đâu.
Những task này ban đầu nhìn có vẻ tốn ít thời gian, nhưng té ra lại thường là loại task tốn kém nhất khiến team trễ deadline.
Nguyên nhân chính khiến những loại task này chiếm nhiều thời gian hơn mong đợi là chúng thường xuất hiện từ các cuộc họp stand-up meeting hàng ngày hoặc qua những cuộc trò chuyện giữa mọi người. Khi DEV không có đủ thời gian để xem xét độ phức tạp của task, họ sẽ đánh giá thấp độ phức tạp và dẫn đến estimate sai.
Do đó, có một TIP cho anh em DEV, là nếu bất chợt PM có yêu cầu làm task gì, hãy cố gắng nhớ cho kỹ yêu cầu của task, sau đấy bình tĩnh về chỗ tìm hiểu estimate và hẹn đưa thông tin estimate cho PM vào một thời gian khác. Anh em còn làm ăn với nhau lâu dài, không việc gì phải vội. Thà làm lâu mà tính năng hoạt động ổn định, còn hơn làm vội mà sau đấy phải mất rất nhiều thời gian để fixbug.
Điều 2. Người nào làm, người đó estimate
Người được giao nhiệm vụ làm task thường là người hiểu rõ hoặc có động lực để hiểu rõ nhất công việc phải làm. Người này sẽ có khả năng nhìn thấy những chi tiết lặt vặt mà cũng không kém phần quan trọng của công việc. Đây là những yếu tố quan trọng để có được estimate chính xác nhất.
Điều 3. Đừng bỏ qua những task lặt vặt
Thường trong quá trình thực hiện project, bạn sẽ nhận được mộ lô những task lặt vặt kiểu như:
Checkbug
Fixbug
Review code
Build App
Deploy App
Nhìn qua thì những việc này không tốn thời gian lắm. Tuy nhiên luôn có vấn đề nào đó xảy ra. Và bạn sẽ khó mà lường trước được độ phức tạp. Hơn nữa, ngay cả khi không có vấn đề, khi bạn cộng gộp thời gian lại, bạn sẽ có được con số không hề nhỏ.
Điều 4. Xem xét tới một vài khả năng gây ra việc delay bất thình lình
Một thành viên nào đó đột nhiên bị ốm, hoặc có kỳ nghỉ mát, hoặc có một vài ngày nghỉ bắt buộc, hoặc một vài bug khủng xuất hiện vào những lúc không ngờ tới. Bạn cố gắng dựa vào kinh nghiệm đã làm của mình, để xem xét đưa những yếu tố này vào kết quả estimate của mình.
Chú ý ở đây là trong quá trình làm project, bạn cố gắng để ý tới các sự kiện không mong đợi, khả năng xuất hiện của bug theo thời gian để có thể có những chú ý cho những lần estimate tiếp theo
Kết luận
Đối với việc estimate, tìm ra các kết quả chính xác thường rất khó. Do vậy, anh em DEV chúng ta nên chấp nhận thực tế này. Tuy nhiên, chúng ta cũng nên estimate càng sát với thực tế càng tốt, dẫu có không thể tìm được kết quả chính xác, nhưng phải luôn cố gắng nỗ lực để làm được điều đó. Quá trình này sẽ giúp anh em DEV chúng ta hiểu biết rõ-ràng và nắm được chính-xác các bước để giải quyết các vấn đề.
Cuối cùng, chúc dự án của anh em hoàn thành đúng hạn!
Thật sự cũng không quá lâu khi chúng ta – những người quyết định sự nghiệp của bản thân là giúp đỡ các tổ chức/công ty mang lại cho người dùng những sản phẩm tốt nhất, tự hỏi làm sao để chúng ta phù hợp trong thế giới phát triển Agile. Trong khi các công ty độc lập và giới kỹ sư phần mềm cố gắng đáp ứng và quyết định rằng Agile là phù hợp với nghiệp vụ và mục tiêu của mình, một sự tiến bộ quan trọng khác đã sẵn sàng xuất hiện trong giới phát triển phần mềm: DevOps. Một vài người còn nhận định, DevOps chỉ đơn giản là một hình thái tiến hóa kế tiệp của Agile.
DevOps thật sự là một sự thay đổi lớn, mà ở đó, nhấn mạnh sự hợp tác giữa các nhà phát triển phần mềm và các chuyên gia trong các lĩnh vực IT khác trong khi tự động hóa việc đưa sản phẩm ra thị trường và thay đổi các cấu trúc hạ tầng. Nó nhằm mục đích xây dựng một môi trường mà ở đó, phát triển, kiểm thử và đưa sản phẩm phần mềm ra thị trường nhanh hơn, thường xuyên hơn và đáng tin cậy hơn.
Về cơ bản, mô hình DevOps phấn đấu để phá vỡ các rào cản truyền thống giữa các bên trong quá trình phát triển, bao gồm cả kiểm thử, nghiệp vụ; và cố gắng đạt đến mức độ tự động hóa việc triển khai sản phẩm phần mềm, nơi mà bất kỳ sự thay đổi và cải tiến nào cũng có thể được triền khai ngay khi cần thiết.
Nếu mục tiêu của chúng ta, như là những kỹ sư kiểm thử, là xây dựng và mang lại sản phẩm nhanh hơn, thường xuyên hơn và đáng tin cậy hơn, chúng ta cần phải sắp xếp và kết hợp các hoạt động kiểm thử, công cụ kiểm thử, kịch bản kiểm thử, dữ liệu kiểm thử và môi trường kiểm thử vào trong một thế giới liên kết liên tục, kiểm thử liên tục và triển khai liên tục các sản phẩm. Xa hơn nữa, chúng ta cần áp dụng các mô hình mới và tập trung vào cách kiểm thử theo hướng phòng ngừa hơn là chăm chăm vào việc tìm kiếm lỗi, và tập trung vào triển khai các chức năng mới vào sản phẩm hơn là vào nghiệp vụ. Nếu không làm như vậy, chúng ta khó hy vọng vào việc nhanh chóng mang lại sản phẩm chất lượng cao cho khách hàng.
Từ đó, chúng ta có cơ hội nhìn lại vai trò, trách nhiệm và công việc kiểm thử của chúng ta trong môi trường DevOps một cách khác biệt. Dưới đây là một vài ví dụ:
Đào tạo, cố vấn và cam kết một cách nghĩ mới, tiếp cận mới về phương pháp cung cấp sản phẩm ra thị trường một cách liên tục thông qua các cải tiến (dù nhỏ) của sản phẩm.
Nâng cao chất lượng trên toàn bộ quá trình phát triển bằng cách không chỉ quan tâm đến chất lượng sản phẩm mà còn chất lượng trong quá trình phát triển, quá trình kiểm thử và quá trình triển khai sản phẩm end-to-end.
Tìm kiếm, đánh giá và thử nghiệm các công cụ hỗ trợ phương pháp làm việc tích hợp, một công cụ áp dụng quá trình làm việc liên tục, có khả năng tăng tốc quá trình phát triển, quá trình kiểm thử, quá trình triển khai và đảm bảo các việc này có thể được làm một cách đồng thời.
Đảm bảo rằng (vấn đề này là cần thiết) luồng làm việc cũng như dữ liệu của người dùng được thu thập và phân tích, bởi tất cả mọi người trong nhóm phát triển, để các chức năng mà ứng dụng cung cấp là dựa trên nhu cầu cần thiết nhất người sử dụng.
Giúp đỡ nhóm phát triển về quản lý và giảm thiểu rủi ro, ví dụ như kiểm thử trên sản phẩm ngay sau khi triển khai; chỉ triển khai những thay đổi/chức năng mới trên một vài hệ thống hoặc vài người dùng; tiến hành trên chế độ phân tích lỗi và đảm bảo có thể quay lại phiên bản trước trong trường hợp có lỗi.
Bạn có thể nói rằng “Những nhiệm vụ này là trách nhiệm của ai đó, không phải kỹ sư kiểm thử“. Theo truyền thống, bạn hoàn toàn đúng. Nhưng, một nền văn hóa đồng nhất và tích hợp mới, nơi mà mọi người hợp tác với nhau để phát triển và cung cấp các sản phẩm phần mềm nhanh hơn, tốt hơn và rẻ hơn đã làm lu mờ các vai trò trong nhóm phát triển.
REST đã được nhiều lập trình viên sử dụng để gửi dữ liệu qua HTTP, trong khi GraphQL thường được biết đến như một công nghệ thay thế của API REST.Trong bài viết này, tôi sẽ giải thích những điểm lợi cũng như hạn chế và sự khác biệt giữa REST và GraphQL. Điều này sẽ giúp bạn quyết định nên chọn gì cho dự án tiếp theo của mình.
REST là gì?
REST (Representational state transfer) là một phương thức tạo API được sử dụng để triển khai các dịch vụ web bằng cách sử dụng một tập hợp các hoạt động không trạng thái được xác định trước (bao gồm GET, POST, PUT, và DELETE).
Ý tưởng cốt lõi của REST là bạn sẽ truy xuất tài nguyên bằng cách đưa qua một yêu cầu tới URL của tài nguyên và nhận được phản hồi (thường là JSON, nhưng nó phụ thuộc vào API).
Lợi thế của REST
REST có khả năng mở rộng, vì nó tách biệt máy khách và máy chủ để bạn có thể mở rộng ứng dụng của mình một cách dễ dàng.
Tính linh hoạt là một lợi thế khác của việc sử dụng REST, vì nó có thể được thiết kế để xử lý các loại cuộc gọi khác nhau và trả về các định dạng dữ liệu khác nhau.
Hạn chế của REST
Over-fetching — Đây là khi endpoint API cung cấp nhiều thông tin hơn so với yêu cầu của khách hàng.
Under-fetching — Đây là khi endpoint API không cung cấp tất cả thông tin bắt buộc.Vì vậy, khách hàng phải thực hiện nhiều yêu cầu để có được mọi thứ mà ứng dụng cần.
GraphQL là gì?
GraphQL là một ngôn ngữ truy vấn dành cho API được tạo ra với mục đích nhắm tới những kiểu dữ liệu phức tạp, đa lớp với nhiều thành phần.GraphQL từ khi xuất hiện đã gần như thay thế hoàn toàn REST bởi tính hiệu quả, mạnh mẽ và linh hoạt hơn nhiều.
Lợi thế của GraphQL
Truy xuất dữ liệu chính xác và chỉ vậy thôi.Trong GraphQL, bạn sẽ nhận được những gì bạn request, đây là một điểm cộng quá tuyệt vời.
Chỉ cần thay đổi phía Client.Thông thường, khi có các thay đổi về yêu cầu dữ liệu, bạn chỉ cần sửa đổi truy vấn và không cần thay đổi nhiều.Cả client và server đều có thể làm việc độc lập, miễn là cả hai đều biết cấu trúc của dữ liệu.
Hạn chế của GraphQL
Có thể hơi phức tạp đối với các ứng dụng đơn giản, để thiết lập các loại truy vấn, v.v., vì nó có thể được thực hiện dễ dàng hơn bằng REST.
Nó sử dụng một endpoint duy nhất thay vì tuân theo HTTP lưu vào cache.Lưu vào cache ở mức độ mạng rất quan trọng vì nó có thể làm giảm lượng lưu lượng truy cập vào máy chủ.
Ví dụ đơn giản để so sánh cả hai
Giả sử chúng ta cần phải hiển thị danh sách bài đăng của tác giả và những người theo dõi họ.Trong trường hợp này, chúng ta phải hiển thị tác giả của bài đăng, bài đăng cũng như những người đang theo dõi người dùng đó.
Nếu sử dụng REST, chúng ta sẽ cần ít nhất 2 hoặc 3 request, như thế này:
/user/<id> để có được thông tin chi tiết về người dùng (tác giả) có thể là tên.
/user/<id>/posts để lấy danh sách các bài được đăng bởi người dùng đó.
/user/<id>/followers để lấy danh sách người đang theo dõi người dùng.
Nhưng trong tất cả những trường hợp này, chúng ta đang over-fetching dữ liệu.Ví dụ, trong request đầu tiên, chúng ta chỉ cần lấy tên, nhưng cái ta nhận được là tất cả các chi tiết về người dùng khi sử dụng cách này.
Và đây là lúc GraphQL cho thấy sức mạnh của nó.Chúng ta cần chỉ định truy vấn và nhận được đầu ra mong muốn.Chúng ta sẽ sử dụng một truy vấn như sau:
query {
User(id: '123') {
name
posts {
title
}
followers {
name
}
}
}
Với truy vấn như này, ta sẽ nhận được JSON response với các thuộc tính sau.Gọn gàng và đơn giản, đúng không anh em
GraphQL và REST
Tóm lại, đây là một vài điểm khác biệt nổi bật:
1.Data fetching
REST gây ra over-fetching hoặc under-fetching, trong khi đây không phải là vấn đề của GraphQL.Trong GraphQL, những điều gì bạn yêu cầu thì bạn nhận được đúng những điều đó.
2. Định nghĩa đối tượng (JSON response)
Với REST, bạn xác định đối tượng trong Backend. Còn với GraphQL, bạn xác định đối tượng trên Frontend.
3. Bộ nhớ đệm tự động
REST tự động lưu vào cache trong khi GraphQL không có hệ thống lưu cache tự động, nhưng có thể khắc phục bằng việc sử dụng các ứng dụng phía client như Apollo Client, Relay, v.v. sẽ mang lại khả năng lưu vào cache.
4. Xử lý lỗi
Xử lý lỗi trong REST đơn giản hơn nhiều so với GraphQL.Tuy nhiên, khi GraphQL sử dụng cùng các ứng dụng phía client như Apollo Client, Relay, … sẽ rất dễ dàng xử lý lỗi.
Kết bài
GraphQL chắc chắn có nhiều lợi thế hơn REST, nhưng nó không phải lúc nào cũng là cách tốt nhất.Như tôi đã nói trước đó, sự lựa chọn phụ thuộc vào ứng dụng của bạn, cho dù chọn REST hay GraphQL.
Tôi hy vọng bài này có thể giúp bạn đưa ra quyết định trong các dự án tương lai.Nếu bạn muốn chia sẻ kinh nghiệm của mình về GraphQL hoặc REST, hãy để chúng trong phần bình luận.Cảm ơn các bạn đã đọc!
Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh
Ahi hi :)) khọc khọc Tôi viết bài thấy mấy anh em chê dễ quá nên thôi tôi giành 1 ít thời gian viết một vài thứ nâng cao cho các anh em đỡ kêu vậy. Bài này ta sẽ tìm hiểu 1 design pattern khá là khó xài, nhưng một khi đã làm chủ nó thì cuộc đời ơi đẹp lắm. Bạn ghi vào CV của bạn là tôi biết PureMVC này, nhận tôi đi nếu không công ty sẽ mất 1 nhân tài đó =)) Tôi đùa thôi. Đôi khi đi xin việc, bạn cũng cần hài hước mà chém gió cho nhà tuyển dụng họ sợ Thôi tôi không khoác lác nữa, dù chém gió hay như nào thì bạn cũng phải biết code nạ
Đầu tiên tôi giới thiệu PureMVC là 1 design phát triển cũng na ná MVC, trong đó:
M = Model(Data)
V= View(Màn hình hiển thị)
C = Controller(Điều khiển).
Nhưng thằng PureMVC nó có các kết nối lỏng lẻo hơn MVC nhiều. Việc tạo ra các kết nối lỏng lẻo như vậy sẽ giúp cho việc phát triển ứng dụng dễ dàng chỉnh sửa, đại tu các thứ. PureMVC hỗ trợ cho actionscript, C++, java, python, ruby.. Nhiều lắm. Anh em lên đây mà đọc nhé:
Ở C++, chúng ta có thể tải code từ đây và build tẹt ga cho window hay các nền tảng khác như linux, Macintosh.. Trích file howtobuild từ source code:
Supporting compilers:
=====================
+ Microsoft Visual C++ 6.0 7.0 8.0 9.0 10.0
+ Minimalist GNU for Windows G++ 3.4.5, 4.x.x (MinGW32)
+ GCC for Linux, MacOS: 3.4.5, 4.x.x
+ Embarcadero C++ Builder 6.21 (Borland C++ Builder in old-name)
+ Digital Mars C++ 8.42n
Supporting operation systems:
=============================
+ Microsoft Windows XP SP3, Micorosoft Windows 7
+ Linux (Fedora 7, CentOS 5.2 64 bit & 32 bit)
+ Macintosh (Tiger X 10.4, Leopard 10.5)
Terminology:
============
bcc: Borland C++ Compiler / Embarcadero C++ Compiler
vc: Visual C++ Compiler
dmc: Digital Marcs C++ Compiler
ic: Intel C++ Compiler
mgw: Minimalist GNU for Windows (MinGW32)
gcc: GNU C++ Compiler
Vậy, anh em làm ứng dụng cho nhiều nền tảng (cross platform) cứ yên tâm là sẽ support tận răng nha :))
Rồi, bây giờ tìm hiểu tiếp các thành phần của framework này.
Proxy: là thành phần của Model. Ổng này là thành phần chuyên xử lý transactions data. Ông request lấy data, ổng lưu, ổng xóa… Ổng này việc đơn giản là thế.Ví dụ ổng request lên server lấy thông tin của 1 user. Sau đó ông ấy lắng nghe data trả về, rồi ông ấy save data này lại vào lớp VO = Các lớp public chứa data của chúng ta. Vậy bạn nhớ cho tôi là Proxy và các VO mà bạn định nghĩa sẽ nằm cùng thư mục là Model.
Mediator: là thành phần xử lý cho View. View là gì? Là khung nhìn, gồm giao diện chứa nút bấm, ô nhập… Các thứ mà người dùng có thể click, chạm, sờ, đập đá.. :)) Ổng vẽ các view lên. Ổng nhận các action này, rồi ông gửi action này cho các thằng khác thông qua sendnotification. Hiểu đơn giản là bắn tin nhắn cho ông nào thích thì cứ nhận mà xử lý. Mọi xử lý thuộc hàm handleNotification(INotification* notification). Ông lắng nghe các notification của những thằng khác, ông xử lý. Ở lớp này anh em nhớ có hàm: onRegister: hàm này để đăng ký lắng nghe các action.
Command: là thành phần của Controller. Nghe cái tên là anh em nó chuyên xử lý. Ông này có hàm execute(INotification* notification) để thực thi các notification nó bắt được. Và nó cũng có thể gửi request cho các thành phần khác xử lý. Đơn giản nó có nhận có gửi xử lý notification.
Các bước mô tả như sau:
Ứng dụng sẽ bắt đầu khởi động với 1 facade. Facade khá trừa tượng, nó là 1 đối tượng quản lý ứng dụng của chúng ta, nó như cái xương sống vậy. Chương trình sẽ bắt đầu từ đây. Ví dụ ta hay đặt tên: ApplicationFacade
Facade sẽ gọi tới hàm startupCommand. Lớp này để khởi động ứng dụng. Khi ta viết với C++, ta sẽ gọi đối tượng facade->statup() và hàm starup sẽ gửi notification cho startupCommand.
StartupCommand sẽ tiến hành đăng ký các proxy và các mediator cần sử dụng trong chương trình thông qua hàm registerProxy(yourproxy) và hàm registerMediator(yourMediator). Đồng thởi ở lớp này thì ông ấy sẽ remove cái command startup luôn. Ví dụ: removeCommand(ApplicationFacade::STARTUP). Sau khi đăng ký xong thì các thành phần này sẽ im lặng và lắng nghe các notificaiton để xử lý. Ông có thể bắn 1 cái notificaiton bật 1 cái view lên, chẳng hạn yêu cầu mở 1 cái view menu chương trình. Mọi thứ của startupCommand đều xử lý ở hàm StartupCommand::execute(INotification* notification). Các message được định nghĩa ở lớp ApplicationFacade.
Application Mediator sẽ đăng ký các tiến trình của mediator
Các process Mediator này sẽ đăng ký View và gửi message để load data.
Facade sẽ nhận các notification này để pass data vào command.
Data command sẽ lọc các notification này và gọi proxy load data.
Proxy sẽ gửi các thông báo cho View thực hiện load data, Mediator sẽ xử lý việc này.
Proxy sẽ gửi các notificaiton cho Mediator xử lý.
…
Cơ bản là như thế. Trong các bài sau tôi sẽ demo bằng visual Studio C++ cho các bạn dễ hình dung. Anh em cứ đọc thêm tài liệu nếu chưa hiểu lắm. Và bắt đầu cài đặt để code thì sẽ hiểu ngay
Đàm phán và thương lương đều là những kỹ năng quan trọng. Thông qua việc đàm phán, thương lượng, các giá trị của bản thân bạn sẽ được bộc lộ một cách tốt nhất. Đối với các freelancer IT, Senior Developer hay bất kỳ vị trí tuyển dung it nào, bạn cũng cần kỹ năng này.
Thế nhưng, nhiều người luôn e ngại về thể hiện mình. Hoặc thậm chí là họ chưa thật sự nắm bắt tốt kỹ năng này. Cùng TopDev tìm hiểu về bí quyết đàm phán và thương lượng thật chất lượng.
Áp dụng Quy tắc 51/49
Hiểu một cách đơn giản, quy tắc này cần bạn đảm bảo mang lại ít nhất 51% giá trị thực tế cho một mối quan hệ.
Việc xây dựng và thiết lập một mối quan hệ đòi hỏi rất nhiều yếu tố. Đó có thể là giao tiếp giữa freelancer it với các khách hàng doanh nghiệp; trao đổi về các lợi ích; đàm phán những rủi ro – thách thức có thể đối mặt,…
Bạn hãy thật linh hoạt, thông minh và cân nhắc xem xét và cố gắng mang lại cho đối tác nhiều lợi ích hơn. Điều này có ý nghĩa quan trọng để duy trì một mối quan hệ lâu dài.
Chấp nhận “đứng thấp hơn 1 bậc” so với đối tác sẽ là một chiến lược thông minh.
Vì khi những gì bạn thỏa thuận giữa freelancer it với khách hàng có xảy ra những phát sinh bất cập từ công ty. Và việc chịu trách nhiệm sẽ không hoàn toàn là do bạn. Và lúc này tiếng nói của bạn có sức nặng hơn.
Dấu ấn lớn từ việc tạo lập các giá trị
Khả năng thuyết phục người khác là một kỹ năng quan trọng cần trau dồi. Và nó ảnh hưởng rất nhiều đến các mối quan hệ của bạn.
Đàm phán gắn liền với mục tiêu, kế hoạch. Khi đó bạn đang đồng thời thể hiện giá trị của bản thân.
Thương lượng thành công hay không là do những cam kết về giá trị và những thành quả hiệu suất; sự cố gắng mà trước đó bạn có được. Một freelancer IT cần cho nhà tuyen dung it thấy được bạn đã trưởng thành ra sao, các dự án bạn thực hiện, kỹ năng -kinh nghiệm của bạn thế nào,…
Khi đàm phán và thương lượng, bạn phải thật bình tĩnh.
Đây là cơ hội tốt để bạn thể hiện tố chất và năng lực lãnh đạo, đàm phán. Hãy tập trung vào việc phân tích và giải pháp.
Bạn phải thể hiện cho họ thấy những mặt hạn chế và đâu là cách thức tối ưu cho các vấn đề. Đặc biệt, hãy trao đổi khách quan và đừng để những cảm xúc tiêu cực lấn át buổi thương lượng của bạn.
Tìm ra điều gì sẽ khiến họ đồng ý
Dù bạn là một freelancer it với trình chuyên môn cao thì mục đích vẫn là làm hài lòng khách hàng thông qua các đề xuất.
Hãy thật sự tinh tế để tìm ra những điểm mấu chốt của vấn đề. Đừng tập trung nói và khai thác, phô bày về bản thân quá nhiều. Hãy trình bày những gì bạn nghĩ là cần thiết cho khách hàng; đúng với nguyện vọng tìm hiểu và hệ giá trị mà họ định hướng khai thác.
Từ cơ sở đó, bạn nên làm mọi cách để đối tác tham gia vào cuộc hội thoại của mình. Đồng thời, thử thách họ bằng các câu hỏi nhằm xác định chính xác hơn nhu cầu; mong muốn của họ một cách tốt nhất.
Lời kết
Đàm phán và thương lượng là cả một nghệ thuật vì nó không đơn giản thuộc về giới hạn giao tiếp. Một điều đáng lưu tâm là hãy đảm bảo là cả đối tác và bạn đều vui vẻ khi rời bàn đàm phán. Chúc cho các bạn sẽ có cuộc đàm phán và thương lượng thật thành công.
4 bước để deal được mức lương như ý với vị trí Product Manager
Tác giả: Dr. Nancy Li
Giới thiệu
Một mức lương tốt sẽ khiến chúng ta cảm thấy vui vẻ hơn khi làm việc. Điều đó là chắc chắn! Nhưng không phải công ty hay vị trí nào cũng có thể cho bạn mức lương tốt như bạn mong muốn. Vậy nên để làm được điều đó, bạn nên có những kỹ năng deal lương để nói chuyện với nhà tuyển dụng. Nhất là ở vị trí Product Manager, đây được xem là kỹ năng cần thiết để có mức lương trong mơ với công việc của mình.
Deal lương tốt cho công việc Product Manager với những mẹo hay nhất
4 bước để deal lương thành công cho Product Manager là gì?
Research – tìm kiếm nhiều nguồn thông tin khác nhau
Hãy cố gắng tìm kiếm thật nhiều thông tin trên internet để tự nhận biết xem hiện tại với khả năng của mình có thể nhận được mức lương cao nhất là bao nhiêu. Và những nhà tuyển dụng đang sẵn lòng trả lương như thế nào cho ứng viên ở công việc Product Manager này. Bạn có thể tìm những thông tin này trên LinkedIn hoặc GlassDoor – những nền tảng cung cấp các thông tin về nghề nghiệp hot nhất hiện nay. Những người đang làm ở đó hoặc những người đã từng làm trong công ty sẽ cho bạn biết hiện rank lương hiện tại của công ty đang ở khoảng nào và cân nhắc.
Value – thành quả tạo được khi trở thành Product Manager là gì?
Hãy nói về những giá trị mà bạn có thể mang lại cho công ty khi tham gia vào các chương trình Product Manager tuyển dụng. Một sai lầm mà rất nhiều người mắc phải khi deal lương với nhà tuyển dụng, đó là họ chỉ chăm chăm nói về những gì đã làm được trong các năm trước, ở những vị trí cũ trong khi công ty cần bạn cung cấp về những gì bạn có thể làm cho công ty hơn.
Những mục tiêu mà bạn đặt ra khi vào làm ở đây là gì? Bạn có thể giúp công ty đạt được những gì? Các thành quả mà bạn làm được sẽ quyết định mức lương bạn có thể nhận được. Sẽ không có nhà tuyển dụng nào muốn trả lương cao cho người không mang lại nhiều giá trị cho công ty. Hãy chứng minh khả năng của mình ngay từ vòng phỏng vấn.
Highball offer của Product Manager là gì?
Lấy ví dụ, nếu bạn muốn được trả mức lương 100.000 USD, bạn đừng bao giờ nói với nhà tuyển dụng rằng bạn luong mong muốn của mình là 100.000 USD. Mà sẽ là 110.000 USD – 115.000 USD, cao hơn một ít so với mức lương bạn thật sự mong muốn. Khi đó, bạn và người phỏng vấn sẽ nói chuyện với nhau và sẽ chốt được số lương thực nhận ở khoảng giữa so với con số đó. Nếu bạn nói đúng mức mình muốn thì lương sau khi thương lượng sẽ thấp hơn.
Tận dụng tốt khả năng đàm phán giúp bạn dễ dàng nói chuyện với nhà tuyển dụng hơn
Sự tự tin
Đây cũng chính yếu tố quan trọng nhất, nhưng không phải ứng viên nào cũng làm được. Rất nhiều người cảm thấy sợ hãi và thiếu tự tin khi đàm phán, thương lượng, nhất là trong lúc deal lương. Do đó để thành công, bạn hãy rèn luyện và cố gắng làm tốt điều mà không phải ai cũng làm được này nếu muốn có được mức lương như mình mong muốn.
Trước đây tôi cũng từng không thích việc phải thương lượng như thế này, nhưng đến một ngày tôi đã thay đổi khi nhận ra rằng: đàm phán đồng nghĩa với ảnh hưởng. Khi bạn đàm phán thành công chính là bạn đã tạo được ảnh hưởng lên một người, một vấn đề nào đó. Hãy thật tự tin cho thấy khả năng của mình để khẳng định rằng mình xứng đáng với mức lương thưởng như thế! Đó là bí quyết của sự thành công.
Để deal được mức lương như ý, ứng viên cần nắm được những bí quyết riêng để dễ dàng đạt được thành công. Dù không phải là tất cả nhưng một mức lương tốt chắc chắn sẽ khiến chúng ta cảm thấy vui vẻ và thỏa mãn hơn khi làm việc ở vị trí Product Manager.
PHP 8.0 là một bản cập nhật lớn của ngôn ngữ PHP. Nó chứa nhiều tính năng và tối ưu hóa mới bao gồm JIT, named arguments, union types, attributes, constructor property promotion, match expression, nullsafe operator và các cải tiến trong kiểu hệ thống, xử lý lỗi và tính nhất quán.
JIT (Just in Time)
JIT được cải tiến hơn và trong PHP 8 giới thiệu hai công cụ biên dịch JIT.
Và Tracing JIT, hứa hẹn nhất vì cho thấy hiệu suất tốt hơn khoảng 3 lần trên các điểm chuẩn tổng hợp và cải thiện 1,5–2 lần trên một số ứng dụng chạy dài cụ thể. Hiệu suất ứng dụng ngang bằng hoặc tốt hơn với PHP 7.4.
Đối số được đặt tên (Named arguments)
Chỉ xác định các thông số bắt buộc, bỏ qua các thông số tùy chọn.
Các lập luận không phụ thuộc vào trật tự và tự ghi lại.
Thay vì các chú thích PHPDoc cho sự kết hợp của các kiểu, bạn có thể sử dụng các khai báo kiểu liên minh gốc được xác thực trong thời gian chạy.
/*** PHP 7 ***/
class Number {
/** @var int|float */
private $number;
/**
* @param float|int $number
*/
public function __construct($number) {
$this->number = $number;
}
}
new Number('NaN'); // Ok
/*** PHP 8 ***/
class Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
Biểu thức hợp nhau (Match expression)
Match là biểu thức mới tương tự như switch và có các tính năng sau:
Match là một biểu thức, có nghĩa là kết quả của nó có thể được lưu trữ trong một biến hoặc được trả về.
Các nhánh so sánh chỉ hỗ trợ các biểu thức một dòng và không cần break; để kết thúc lệnh.
Match không so sánh chặt chẽ.
/*** PHP 7 ***/
switch (8.0) {
case '8.0':
$result = "Oh no!";
break;
case 8.0:
$result = "This is what I expected";
break;
}
echo $result;
//> Oh no!
/*** PHP 8 ***/
echo match (8.0) {
'8.0' => "Oh no!",
8.0 => "This is what I expected",
};
//> This is what I expected
Toán tử Nullsafe (Nullsafe operator)
Thay vì điều kiện kiểm tra null, bây giờ bạn có thể sử dụng một chuỗi các cuộc gọi với toán tử nullsafe mới.
Khi đánh giá một phần tử trong chuỗi fails, quá trình thực thi của toàn bộ chuỗi sẽ bị hủy bỏ và toàn bộ chuỗi được gán là null.
Nhất quán lỗi cho các chức năng nội bộ (Consistent type errors for internal functions)
Hầu hết các chức năng nội bộ hiện ném Error exception nếu việc xác thực các tham số không thành công.
/*** PHP 7 ***/
strlen([]); // Warning: strlen() expects parameter 1 to be string, array given
array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0
/*** PHP 8 ***/
strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given
array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0
Chia sẻ của bạn Nguyễn Dương Hải về việc sử dụng kiến thức SQL trong quá trình làm test.
Mình không dám nói mình làm DB test nhiều. DB test, nếu làm hoàn chỉnh có rất nhiều phần bạn phải take care ví dụ như Performance của câu SQL, DB indexing, … Nhưng ở bất cứ dự án nào mình cũng đều cố gắng tìm hiểu Database structure của hệ thống. Mục đích chính là xem data flow đi như thế nào khi sử dụng feature trên UI, rồi từ từ mình cũng test một số feature bằng cách viết SQL. Sau đó mình học được những mẹo nhỏ để sử dụng kiến thức Database cua project và SQL để phục vụ cho công việc test của mình tốt hơn, tìm ra được nhiều case hơn. Mình xin phép nói về những trường hợp mình can thiệp vào DB và can thiệp thế nào để có hiệu quả tốt nhất.
1/ Test một feature khi những feature liên quan chưa sẵn sàng
Mình tin rằng bạn nào cũng đã từng gặp những trường hợp như thế này. Ví dụ:
Feature tạo đơn hàng đã xong.
Nhưng feature để xem danh sách đơn hàng vẫn chưa làm xong
Thông thường, ta cần có feature xem danh sách đơn hàng để một lúc kiểm tra 2 chuyện: tạo đơn hàng thành công và list đơn hàng đúng. Tuy nhiên, về mặt bản chất, tạo đơn hàng xong rồi thì chỉ cần kiểm trong database xem nó có lưu đúng field, đúng value không là được.
Thoạt nghe đơn giản nhưng bạn sẽ thấy có những feature rất phức tạp mà team bạn mất nhiều ngày mới làm xong. Nếu bạn làm tới đâu kiểm tới đó sẽ chỉ có lợi.
2/ Test Back End bằng cách check SQL
Ngắn gọn là, có những feature mà Back End chủ yếu là làm ra 1 câu SQL đưa data lên cho Front End, lúc đó là có gì in ra đó. Tìm hiểu câu SQL đó có thể cho bạn những ý tưởng thú vị để test, hoặc chỉ đơn giản là Analyze nó ra để xem họ có làm đúng logic không?
Đây là một trong những ứng dụng mà mình thích nhất khi đã hiểu tường tận DB của product rồi. Một ví dụ đơn giản, bạn test chức năng Sign Up, bạn phải test 10 case. Chỉ mỗi chuyện tạo 10 email để test thôi là mệt thở rồi. Nhưng mà, nếu bạn biết cách vào trong database, mình tin rằng bạn chỉ cần edit 1 field “email” trong 1 table nào đó là cái email ban đầu của bạn sẽ free ngay.
Tóm lại, bạn sẽ có thể sử dụng email hainguyentesting@gmail.com bao nhiêu lần tùy thích để nhận được email confirmation và test nó.
Clean data
Dùng trong trường hợp bạn muốn test environment của bạn được sạch sẽ để demo cho client, để test case empty data, hoặc có quá nhiều data rác làm bạn rối trí. Lúc này, chưa chắc trên Front End của bạn đã có feature REMOVE, mà nếu remove bằng tay thì cũng chết.
1 câu lệnh DELETE sẽ giúp bạn tiết kiệm rất nhiều thời gian:
DELETEFROM table_name [WHERE Clause]
WARNING! Để đảm bảo được tính thống nhất của data, bạn phải chắc chắn rằng bạn hiểu rõ database structure của product bạn. Ví dụ, nếu bạn muốn delete 1 row User đi thì trước tiên bạn phải remove những đơn hàng của user đó trong table don_hang trước. Nếu không database sẽ báo lỗi khi bạn cố gắng remove, hoặc là data bạn test sẽ không còn đúng nữa. Keep that in mind!
Dump initial data
Với những tình uống sau đây, bạn nên cân nhắc tạo ra 1 bộ data chuẩn và lưu giữ nó lại:
Bạn đang cần 1 lượng data lớn để test performance
Bạn không muốn client của bạn phải vào test khi chưa có 1 data nào trong website sau mỗi lần deploy.
Bạn đang cần 1 bộ data gồm nhiều case, giả sử như First Name có đủ kiểu từ chữ thường cho đến tiếng Hoa, Tiếng Hàn, “?!@#”,… để test layout.
Bạn đang muốn test case: structure của Dabase cũ sẽ được migrate sang thành structure mới khi server bạn start
Automation test case của bạn cần phải có 1 bộ data chuẩn, vì test case được thiết kế để kiểm tra đúng sai trên đúng bộ data đó! Là cái khác, sai 1 chút thì sẽ có 1 test case fail.
Với những trường hợp như trên mình đề nghị:
Bạn tạo ra 1 bộ data test với những data bạn cần. Khi tạo data, mình dùng câu lệnh INSERT, hoặc những website như https://www.mockaroo.com/ sẽ giúp bạn làm chuyện này tốt hơn. Học cách sử dụng những “data generator tool” không khó.
Nếu bạn muốn chắc ăn. Hãy tạo data trên UI, nhưng mình không khuyến khích vì nó sẽ tốn thời gian và phụ thuộc vào độ support của UI.
Sau đó, dump nó ra thành 1 file SQL. Trong SQL tools hoặc thậm chí là command line luôn có cách để làm vụ này
Khi nào cần, thì dùng chức năng backup file SQL ( có cả command line) để dump data ngược trở vào, đè lên toàn bộ data cũ.
Với cách này, mỗi lần test, bạn có thể ung dung test những case bạn cần với data có sẵn. Thậm chí bạn đã biết trước kết quả sẽ như thế nào nên việc testing cũng sẽ dễ dàng
WARNING! Những side effect sau đây cần phải được cân nhắc:
Team bạn đang thực hiện testing và data của họ bị xóa. Đặc biệt là client. Nếu bạn đang dùng chung 1 environment, thì phải có sự đồng thuận của tất cả mọi người
Update data test để có structure mới nhất.
Ví dụ, mình tạo ra 1 bộ data test, lúc đó database chỉ có field email, username và password thôi. Một thời gian sau, mình có thêm 1 field mới nữa là Name. Khi mình dump data test cũ vào, hệ thống báo lỗi.
Nếu team bạn có làm migration tốt, đó sẽ là một test case hay. Nhưng nếu team bạn không có kế hoạch làm nó, thì bộ data test của bạn phải được update structure thường xuyên, nếu không sao khi dump data, feature của bạn có thể chạy sai.
4/ Query real data sẽ giúp bạn thấy những điều thú vị
Tìm ra lỗi
Câu chuyện về cách đây 4 năm, mình làm cho 1 dự án Social Network. Team mình collect từ fanpage của những ca sĩ, username của những fan hâm mộ họ rồi blah blah. Lúc đầu, team mình cứ đinh ninh rằng username sẽ không có dấu “?” nên lúc thiết kế UI để render ra cái list này cũng chẳng support nó. Đến một ngày đẹp trời, mình query trên production và thấy chuyện này là có thể khi hệ thống mình capture được 1 vài user như vậy, sau đó thì fix Front End.
Analytic
Cũng trong dự án đó, client thường hay request team theo kiểu:
Nói cho tui biết trong 1 tháng qua có bao nhiêu đứa có 2000 fan trong hệ thống.
Có đứa nào trong 1 tháng tăng được 500 fan không?
…
Mình biết công việc này thường rơi vào Dev lead, nhưng nếu mình có thể sao lại không làm? Nếu bạn muốn đề xuất add thêm feature mới hoặc remove feature cũ, bạn sẽ cần data query như là 1 back up cho lập luận của bạn đó
Lời kết
Hy vọng sau bài viết này bạn có thể sử dụng kỹ năng SQL của mình đúng lúc và cân nhắc tất cả những hậu quả có thể có để có thể test một cách nhanh và hiệu quả nhất. Chúc các bạn thành công.
Bài viết được sự cho phép của tác giả Edward Thiên Hoàng
Có lẽ thuật ngữ “đánh index” đã quá quen với những ai làm việc với CSDL, đó là cách rất phổ biến để tăng tốc độ query của dữ liệu, khi dữ liệu Database ngày càng tăng và trở nên chậm dần đều theo thời gian. Mục tiêu của việc tạo Index là để tăng tốc độ trả về dữ liệu của một hoặc nhiều trường (rows) trên một bảng (table) cụ thể nào đó bằng cách tạo Index trên một hoặc nhiều cột (columns) của một database table.
Để hiểu rõ hơn thế nào là Indexes ta hãy đến thử một nhà sách hay thư viện, thường các cuốn sách sẽ được phân chia theo các danh mục về nội dung như: sách nấu ăn, sách tiểu thuyết nước ngoài, sách tâm lý, sách lịch sử … Nếu ta muốn tìm kiếm một loại sách theo nội dung mong muốn thì chỉ việc tới cá kệ sách với nội dung tương ứng, nó sẽ nhanh hơn là tìm kiếm từ toàn bộ cả nhà sách từ. Hoặc ví dụ khác về các phần mục lục trong muốn cuốn sách, nếu ta muốn tìm nhanh đến “chương hồi” ta đang cần tìm kiếm hoặc đọc dở chỉ cần tra mục lục rồi tìm tới đúng trang chứa nội dung.
Index trong Database cũng giống như vậy, ví dụ ta có một table là Books chứa 4 columns là “book_title”, “writer”, “subject”, và “date_of_publication”, thường thì khách hàng sẽ thường xuyên tìm kiếm sách theo hai tiêu chí là tên sách và tác giả, do đó ta sẽ tạo Index cho hai column là “book_title” và “writer”. Database sẽ tạo ra một data structure riêng biệt chứa hai giá trị của toàn bộ nội dung (content) các cột đánh index và một con trỏ (pointer) để trỏ tới dữ liệu thật sự đang nằm ở Database. Như vậy, sử dụng index yêu cầu cần disk space để chứa cấu trúc của nó và Index cũng không làm thay đổi cấu trúc của table. Do vậy mỗi làm tìm kiếm dữ liệu thì Database sẽ tìm kiếm ở Index sau đó dựa vào con trỏ của Index để trả về dữ liệu thật.
Nhưng tại sao tìm kiếm trên Index lại nhanh hơn tìm kiếm trên Database, bởi vì Index luôn luôn sắp xếp dữ liệu để tối ưu nhất cho các thuật toánthực hiện việc tìm kiếm, còn dữ liệu Database thật thì luôn sắp xếp lộn xộn không có thứ tự nên không thuận tiện cho việc tìm kiếm. Mỗi Database sẽ có cách sắp xếp Index và thuật toán tìm kiếm Index khác nhau.
Tuy nhiên Index cũng không phải là một magic keyword, việc đánh Index cần thật cẩn trọng, – Thứ 1: Việc tạo Index sẽ tốn disk space, do đó chỉ nên đánh những cột dữ liệu có dung lượng nhỏ, và sẽ không có ý nghĩa gì nếu đánh Index cột contents kiểu CLOB chứa nội dung của một article vì lúc đó dữ liệu của Index sẽ to bằng nguyên cái table gốc. – Thứ 2: Index thì ta cũng phải cần tạo ra nó, với một dữ liệu lớn sẵn rồi mà lúc này ta mới đánh Index thì việc tạo ra nó là một công việc rất tốn thời gian và tài nguyên hệ thống. Cho nên tốt nhất hãy lường trước ta tạo Index ngay từ khi dữ liệu còn nhỏ. – Thứ 3: Việc dữ liệu được thêm mới sửa xóa (CUD) thường xuyên trên Table gốc thì Index cũng sẽ phải thêm mới sửa và sắp xếp lại, với một Table có dữ liệu lớn thì việc này cũng rất mất thời gian và nó sẽ làm chậm đi quá trình update hay create dữ liệu từ table gốc.
Do đó chỉ những Index thực sự cần thiết mới nên thêm vào và nên thường xuyên xem xét lại và xóa những Index không thực sự cần thiết. Và mục tiêu chính của Index đó là tăng khả năng đọc (read) của dữ liệu, do đó những Table dạng thường xuyên ghi nhưng ít khi được đọc thì tốt nhất không nên tạo Index, vì nó sẽ giảm hiệu xuất của việc ghi dữ liệu.
Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh
Xin chào mọi người, lại là tôi Xuân Quỳnh đây
trong bài trước, các bạn đã làm quen với kiểu con trỏ qua ví dụ với con trỏ kiểu char. Bài hôm nay anh em sẽ tiến hành đi vào vấn đề chính là viết 1 thủ tục printf thay thế.
Chúng ta quay trở lại với thủ tục đã định nghĩa như sau:
void inramanhinh(char*caicaninra)
Bây giờ tôi sẽ giới thiệu 1 kiến thức mới, đó là thay vì bạn nhâp 1 ký tự thì bạn chơi với 1 chuỗi ký tự. Ví dụ chuỗi “abcd” chẳng hạn. Ký tự thì đặt trong nháy đơn, còn chuỗi thì nháy đôi các bạn nhé. Ví dụ tôi khai báo như sau:
Ở đây tôi sử dụng 2 kiến thức mới:
Mảng: Mảng là gì? Là 1 kiểu tập hợp các phần tử đơn thành tập để tiện quản lý. Ở đây tôi dùng pc[10] nghĩa là tôi tạo mảng 10 phần tử, được đếm từ 0 tới 9. Tôi đồng thời gán luôn 3 giá trị đầu lần lượt là a, b, c. Sau này trở đi, để khai báo mảng bạn dùng cú pháp như sau:
[Kiểu dữ liệu] [tên của biến][Số lượng phần tử]
Ví dụ:
int mangnguyen[100];
float dayso[20];
Vòng for: Vòng for dùng để thực hiện những việc lặp đi lặp lại, để code bạn viết ngắn gọn lại. Nếu ví dụ trên không dùng vòng for, bạn cũng có thể in ra 3 dòng như sau:
Giả sử bạn có 100 chữ cái thì bạn viết ra 100 dòng :)) Vậy bạn đã biết ý nghĩa của vòng for như nào rồi đó.
Cú pháp vòng for như sau:
for (giá trị khởi tạo; điều kiện dừng; nếu đúng điều kiện dừng thì làm việc ở đây)
Tôi sẽ giới thiệu vòng for kỹ hơn vào các bài sau. Tạm thời bạn biết thế đã
Khi cấp phát mảng 10 phần tử bạn hình dung bộ nhớ được phân phối như sau:
Bộ nhớ gồm 2 phần, 1 phần đánh địa chỉ từ 0, trên hình tôi để dạng hexa. Phần 2 là giá trị nằm trên ô nhớ đó. Ở đây tôi dùng kiểu char, cho nên 1 ô nhớ có kích thước đúng bằng sizeof(char). Vậy bạn có 10 ô, được đánh số từ 0 tới 9. Vậy, nếu bạn muốn dùng con trỏ thì làm như nào. Tôi sẽ dùng con trỏ khởi tạo 10 ô tương tự trên nha, đảm bảo không hiểu không tính tiền luôn :))
Ố ồ, nhìn có hoảng không các mem mới Tôi mà mới học tôi cũng hoảng. Nhiều cái mới quá. Ta tiến hành bóc tách từng thứ 1.
Đầu tiên là dòng thứ 2:
#include < stdlib.h >
Đây cũng là 1 thư viện mới. Tôi dùng hàm malloc cho nên tôi cần thư viện này. Nếu bạn build bằng gcc mà quên không include vào thì nó cũng báo cho bạn biết
Dòng này là chủ đạo:
pMangChu = (char*) malloc(sizeof(char) * 10);
Trông nó hoa vện như con giun ấy nhỉ. Để hiểu câu lệnh trên, ta xem hàm nguyên mẫu của các ông bên UK, US định nghĩa nó như nào nhé:
Bạn dịch hộ tôi cái. Còn tôi sẽ diễn giải đơn giản như này. Bạn thấy từ khóa void. Bạn thấy quen, nhưng ở đây thêm dấu *, nghĩa đây là con trỏ kiểu void. void là 1 kiểu dữ liệu chung chung, muốn trả về kiểu gì cũng được. Phía bên trong hà m malloc ta thấy dòng size_t size, bạn hiểu nó là chứa 1 cái số để cấp phát dữ liệu. Bạn thêm 100 thì nó cấp cho 100 byte, bạn cho 1000 thì nó cấp cho 1000 byte. Số cho vào đó phải là số dương!
tôi ép kiểu (char*) để void* thành char* (vì nó trả về kiểu gì cũng được mà, con trỏ là ok).
Phía trong tôi không cho 100 hay 1000 đâu nha, cho lung tung tạch bộ nhớ máy tính thì chết. Tôi tính kích thước của ông char xem bao nhiêu bằng hàm sizeof(char). Hàm sizeof này trả về đúng kích thước của kiểu, tính theo byte. Ví dụ trong hệ 32 bit thì kiểu int là 2byte, còn trong hệ 64bit là 4byte. Chẳng hạn như thế. Mỗi máy 1 thể loại nên tôi không cho số được mà tôi nhờ máy tính tính hộ cho tôi. Sau đó tôi nhân với 10 để tạo ra 10 ô nhớ liên tiếp. Tổng hợp lại là sizeof(char) * 10
Tiếp theo câu lệnh:
free(pMangChu);
Cái này là giải phóng con trỏ này, chương trình sẽ thu hồi 10 ô nhớ mà bạn vừa cấp phát ở trên. Từ sau lệnh này pMangChu coi như là đã chết :)) Bạn mà dùng lại nó thì sinh ra lỗi ngay. Không tin cứ thử gán *pMangChu = ‘a’ xem
Bạn nhớ vào đầu cho tôi, nói hơi bẩn tí là bạn ăn vào thì bạn phải ỉa ra, bạn nợ tiền ai thì bạn phải trả, đấy là quy luật ở cuộc sống rồi, có vay có trả. Bạn có vay bộ nhớ thì bạn phải trả cho nó. Bạn mà không trả thì chương trình sẽ sinh ra lỗi trong quá trình chạy như thiếu bộ nhớ, hay còn gọi là leak of memory. Cho nên cứ khắc vào đầu cứ malloc thì free. Cứ viết ra như thế cho đỡ quên. Ở các ngôn ngữ khác nó tự xử lý, cho nên năng suất chương trình không bằng C la điều đương nhiên rồi. Bạn chơi với con trỏ, bạn có quyền năng cao hơn java hay C#.
Bây giờ bạn muốn gán giá trị cho từng phần tử thì làm thế nào. Có 2 cách:
Bạn xem dòng 12 tới dòng 13. Tôi gán bình thường như bạn dùng mảng đã nói ở trên. Sau đó tôi in ra ký tự vị trí số 0(đầu tiên) đó.
Dòng 15 tới 16: Bạn nhớ cho tôi 1 điều, để lấy địa chỉ của 1 biến con trỏ, bạn cứ để nguyên tên pMangChu thì nó là địa chỉ. Muốn xem giá trị nằm trên địa chỉ này thì thêm * phía trước. Tôi dùng *(pMangChu) hay *(pMangChu + 0) là phần tử đầu tiên, *(pMangChu + 9) là phần tử thứ 10. Do vậy phép gán dòng 15 cũng tương tự với dòng 12.
Nhớ vào đầu cho tôi:
Dùng * để truy cập giá trị và để nguyên tên của biến con trỏ để truy cập địa chỉ!
Nhớ vào đầu cho tôi nhé các bạn trẻ =))
Bây giờ C nó cung cấp cho 1 thể loại không cần cấp phát bao nhiêu ô nhớ mà nó tự tính. Cụ thể như sau:
Kết quả chạy chương trình:
Quay lại xem code. Dòng thứ 9 bạn thấy rõ ràng C cho phép gán biến con trỏ luôn cho 1 xâu. Ở đây xâu này là mảng gồm các phần tử sau:
A, n, h, dấu cách, n, h, o, dấu cách, e, m, \0 (dấu kết thúc dòng)
Vậy tôi đếm bằng tay thì có 10 phần tử nhìn thấy được, tôi for từ 0 tới 9 để in ra, đó là câu lệnh 10. Cuối chương trình tôi free nó ra :)) Có vậy thôi.
Bạn thấy C ngon chưa. Ngon đúng không? Vậy chén tiếp thôi.
Rồi, nói mãi mãi vẫn chưa tới thủ tục:
void inramanhinh(char*caicaninra)
Bây giờ nhìn thủ tục trên bạn không sợ con trỏ caicaninra nữa rồi. Nó gọi là parameter, là tham số truyền vào thủ tục để làm gì đó, như cái miệng bạn há ra để dốc cơm vào, vào ruột thì nó xử lý thế nào kệ ruột nà.
Tôi viết hàm như sau:
Kết quả như sau:
Đáng yêu chưa =))
Rồi tôi giải thích. Bạn viết thủ tục inramanhinh và bạn phải đặt trước main, thì ông main ông ấy mới hiểu là trên đời này còn có 1 ông sinh ra trước, ông ấy mới cho phép dùng bên trong thân hàm ông ấy được. Có cách như này cũng được nè:
tiền trảm hậu tấu, khai báo trước, định nghĩa sau :))
Để hiểu thủ tục tôi viết, bạn quay về với hàm printf nguyên thủy của C:
Hàm này nhận vào 1 con trỏ kiểu char và kèm các tham số phía sau. Ở đây tôi cũng dùng con trỏ là 1 char* caicaninra nên khi tôi dùng câu lệnh 15 thì nó OK đúng chuẩn ISO rồi nhá
Tôi muốn các bạn muốn học C cho bài bản thì đọc kỹ hướng dẫn các hàm này ở google. Bạn có thể xem ở đây chẳng hạn.
Vậy là bạn đã biết cách viết 1 thủ tục làm việc cho bạn rồi đúng không Bạn thấy tốt cả chứ?
Bài tập cho các bạn:
Hãy viết 1 hàm in ra tên bạn.
Viết 1 hàm tráo đổi 2 số
Bạn nào mà coi trọng bài học này thì làm bài tập rồi comment ở dưới cho tôi code của các bạn nha.
Bài tiếp theo tôi sẽ hướng dẫn các bạn dùng makefile để build nhiều file chứ không 1 file như mấy bài đã học. Sẽ vui lắm đó. Toàn kiến thức cơ bản không :))