Xin chào các bạn, bài viết hôm nay mình sẽ hướng dẫn các bạn cách định dạng Ngày tháng và Thời gian trên Windows và Ứng dụng trong lập trình C#, Winform.
Khi các bạn viết ứng dụng winform hay ứng dụng nào của windows, thì mặc định các control ngày tháng hay thời gian, sẽ mặc định sẽ lấy format cấu hình của máy tính.
Cấu hình DateTime Format ở Windows của mình:
Theo hình trên, thì người sử dụng cài đặt mặc định Short Date Format là: MM/dd/yyyy
Thì khi chúng ta chạy ứng dụng của mình thì các control cũng format theo định dạng đó, như hình bên dưới đây:
Các bạn xem hình ảnh trên sẽ thấy thay vì hiển thị ngày 03/12/2020 => nó lại đi hiển thị là 12/03/2020.
Nếu mặc định người dùng biết chỉnh định dạng format ngày tháng lại thì đơn giản không sao.
Nhưng mong muốn của mình là khi chạy ứng dụng của mình sẽ luôn thể hiện ở định dạng format chuẩn Việt Nam dd/MM/yyyy.
Dưới đây mình sẽ có ba cách thực hiện như sau:
Cách 1: Chỉnh Regedit của Windows về định dạng mong muốn của mình
Cái này là mình định dạng theo chuẩn format về 24h.
Kết quả chạy như hình ảnh bên dưới đây:
Tuy nhiên trong ứng dụng, chúng ta nên thực hiện theo cách thứ 3 ở bên dưới đây:
Cách 3: Cài đặt ngày tháng và thời gian mặc định của ứng dụng khi chạy Current Thread
Thay vì chúng ta đi chỉnh định dạng ngày của người sử dụng, thì không hay, nhiều lúc người dùng vẫn mong muốn định dạng máy tính của họ là MM/dd/yyyy.
Hay bất kỳ định dạng nào. Tuy nhiên, chúng ta làm sao để khi mở ứng dụng của mình lên chạy đều thể hiện ở định dạng dd/MM/yyyy thì chúng ta sẽ sử dụng cách dưới đây nhé.
Các bạn cấu hình trực tiếp ở file Program.cs nhé như code bên dưới đây.
staticclassProgram{/// <summary>/// The main entry point for the application./// </summary>[STAThread]staticvoidMain(){
Application.EnableVisualStyles();initCulturalFormattingChanges();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(newForm1());}privatestaticvoidinitCulturalFormattingChanges(){CultureInfo cultureDefinition =(CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
cultureDefinition.DateTimeFormat.ShortDatePattern ="dd/MM/yyyy";
cultureDefinition.DateTimeFormat.ShortTimePattern ="HH:mm:ss";
Thread.CurrentThread.CurrentCulture = cultureDefinition;}}
Mẫu Đơn xin việc có những điều gì đáng lưu ý? Đâu là những điểm đáng lưu ý cho một mẫu đơn xin nghỉ việc đúng chuẩn theo yêu cầu? Cách viết một đơn xin nghỉ việc như thế nào?
Như chúng ta đều biết, nhu cầu nghỉ việc, thôi việc là nhu cầu thiết yếu của người lao động. Tùy vào quy mô tổ chức, vận hành mà chế độ và hình thức nghỉ phép sẽ có điểm khác nhau. Do vậy mà đơn xin nghỉ việc thật sự rất quan trọng. Đồng thời, một lý do xin nghỉ việc chính đáng cũng rất quan trọng! Cùng TopDev tìm hiểu và giải đáp các thắc mắc xoay quanh mẫu đơn xin thôi việc nhé!
Đơn xin nghỉ việc là gì?
Đơn xin nghỉ việc là một loại giấy tờ có hiệu lực và giá trị pháp lý, đảm bảo yếu tố hiện hành về yêu cầu thôi việc của một cá nhân trong một lĩnh vực hoạt động cụ thể nào đó. Loại văn bản này là quyền lợi của mỗi nhân viên. Văn bản này giúp nhân viên trực tiếp hoặc gián tiếp phản ánh sự vắng mặt của bản thân trong một khoảng thời gian được xác định và có giới hạn.
Chúng ta có thể xem xét nó như một loại văn bản cần có trong quy trình quản lý và phát triển tổ chức nhân sự ở mỗi cấp doanh nghiệp. Đơn xin nghỉ việc cần được thể hiện giá trị của nó đúng thời điểm. Điều này phản ánh cho tính trách nhiệm mà mỗi nhân viên thể hiện thông qua sự chuyên cần.
Tại sao cần phải viết đơn xin nghỉ việc?
Chắc hẳn khi muốn nghỉ việc, ai cũng mong muốn “đẹp lòng” cả đôi bên. Do vậy, một đơn xin nghỉ việc với đầy đủ thông tin, nội dung hợp chuẩn; được viết với thái độ chuyên nghiệp và thể hiện sự tôn trọng cần có với tổ chức sẽ giúp lưu giữ những giá trị tốt đẹp hơn.
Lý do xin nghỉ việc rất quan trọng
Mẫu đơn xin thôi việc thể hiện bạn là người có tính trách nhiệm với vị trí, sự tín nhiệm mà tổ chức dành cho bạn trong thời gian vừa qua.
Nó cũng là cơ sở quan trọng giúp cho quá trình nghỉ việc được thuận lợi và có tính chuẩn mực hơn. Vì thế, trong bất kỳ hoàn cảnh nào và bất cứ lý do nào, bạn cũng cần phải viết đơn xin nghỉ việc.
Phân loại mẫu đơn xin nghỉ việc
Thực tế trong tổ chức quản lý nhân sự, có rất nhiều mẫu đơn xin việc. Vậy bạn đã bao giờ biết rõ về chúng? Cùng điểm qua 3 loại mẫu đơn xin nghỉ việc, thôi việc chuẩn nhất.
Khi cá nhân người lao động có ý định nhảy việc, muốn chấm dứt hợp đồng thì nhu cầu viết đơn thôi việc là tất yếu diễn ra.
Mục đích của đơn này là trình bày chi tiết lý do và thông báo cho công ty về việc thay đổi nhân sự. Từ cơ sở đó, họ có kế hoạch tuyển dụng kịp thời cho các vị trí còn trống.
Đồng thời, đơn xin nghỉ việc củng có ý nghĩa lớn khi là văn bản giải trình; hỗ trợ quá trình thiết lập sự minh bạch về quy chế nhân sự, tránh tình trạng vi phạm hợp đồng hay những phát sinh tiêu cực ngoài ý muốn.
Tất nhiên, để được phê duyệt và xử lý theo quy trình, đơn nghỉ việc và lý do xin nghỉ việc của cá nhân phải đảm bảo tính thuyết phục, chuyên nghiệp.
2. Đơn xin thôi việc, nghỉ phép không lương
Nếu bạn là cá nhân thuộc các trường hợp như: ốm đau, có việc riêng cần giải quyết; hoặc không có thời gian để bàn giao các nhiệm vụ;… Đây là lúc thích hợp để bạn nêu rõ các lý do của mình.
Một điểm cần lưu tâm là bạn cần có thiện chí nghỉ việc không lương để có thể nhận được sự thông cảm từ nhà quản lý/tổ chức nhân sự. Đừng khiến bản thân rơi vào các tình trạng vi phạm hợp đồng!
3. Đơn xin thôi việc tạm thời (thời gian ngắn)
Đã là một nhân sự chính thức, bạn cần tuân thủ mọi điều luật và chế độ quản lý được đặt ra. Vì vậy, dù là tạm nghỉ có thời hạn và quay trở lại, bạn cũng cần viết đơn xin nghỉ việc. Điều này thể hiện bạn là người có trách nhiệm với tổ chức.
Các bạn lưu ý, cách viết cho loại đơn xin nghỉ việc này là thông báo tới công ty về: lý do, thời gian trở lại làm việc,… Không khó để nhận được sự chấp thuận nếu ban có cách trình bày lý do chính đáng và một thái độ chuyên nghiệp.
Những lý do viết đơn xin nghỉ việc
Tùy vào từng trường hợp cụ thể mà mỗi cá nhân có lý do xin nghỉ việc tương ứng. Cùng điểm qua các lý do viết đơn thôi việc hợp lý, chính đáng và ngược lại.
1. Các do xin nghỉ việc chính đáng
Mong muốn đổi môi trường làm việc phù hợp hơn.
Những định hướng phát triển hiện tại không đúng với kỳ vọng.
Các vấn đề về di chuyển cá nhân.
Chế độ đãi ngộ không tương xứng với sự nỗ lực cá nhân.
Sự thăng tiến chậm hoặc nhận thấy không có cơ hội nào để tiếp tục phát triển trong sự nghiệp.
Những “nội chiến” từ các mâu thuẫn, bất đồng công sở.
Ảnh hưởng đa chiều từ các công việc bên ngoài.
Các lý do cá nhân: tâm lý, tình cảm.
Văn hóa công ty chưa thực sự phù hợp với cá tính.
Có những môi trường làm việc lý tưởng hơn.
2. Các lý do xin nghỉ việc không chính đáng
Có nhiều lý do nghỉ việc được đặt ra trong lá đơn trình bày.
Hoàn cảnh gia đình không cho phép.
Bất khả khàng trong việc kết nối mọi người.
Xu hướng tâm lý và cảm xúc cá nhân chi phối.
Chưa hài lòng với lịch trình làm việc và các quy tắc của công ty.
Công việc nhàm chán, thiếu tính bức phá và các cơ hội sáng tạo.
Với những lý do chính đáng trên, chắc chắn là bạn không nên sử dụng.
Đơn giản vì nó không được nhà quản lý đánh giá cao bạn. Mọi cố gắng của bạn có thể bị mất đi. Trong việc viết đơn, bạn nên thành thật chia sẻ những lý do của bản thân. Đừng nói dối trong mọi trường hợp. Một khi sự thật được phát hiện, bạn mất đi uy tín lẫn cả những tình cảm của cấp trên, các đồng nghiệp đối với bạn. Vậy nên, hãy chân thật khi viết đơn xin thôi việc.
Nếu đã xác định rõ lý do nghĩ việc, bạn cũng nên lập ra kế hoạch trở lại; hoặc sự chuẩn bị tốt nhất cho thời gian mà bạn vắng mặt. Đồng thời, bạn hãy tìm kiếm cho bản thân những mẫu đơn xin nghỉ việc hợp lý, đúng chuẩn để có thể thuận lợi chuyển sang một môi trường làm việc thích hợp hơn. Ra đi hay ở lại thì bạn đều phải để lại ấn tượng đẹp với tổ chức/doanh nghiệp của mình.
Việc cần làm đầu tiên là bạn cần thông báo cho người quản lý, ngưới giám sát hoặc các cấp cao hơn. Tùy vào mỗi công ty, bạn phải thực hiện thông báo về Team Leader hay phòng nhân sự khoảng 15-30 ngày trước khi chính thức thôi việc. Đây là khoảng thời gian tương ứng với phụ lục pháp lý được trích trong hợp đồng lao động.
Và việc bạn cần làm là tuân thủ chúng. Đây cũng là thời gian công ty có thể sắp xếp và tuyển chọn nguồn nhân sự mới cho vị trí bạn nghỉ việc. Việc báo trước cho nhân sự phản ánh bạn là một cá nhân có thái độ tốt và tính trách nhiệm cao.
2. Bàn giao công việc và những thứ có liên quan
Khi lá đơn xin thôi việc của bạn được duyệt, kế tiếp chính là bước bàn giao công việc. Trong thời gian đó, nhiệm vụ của bạn là phải hoàn tất các công việc dang dở trong thời gian quy định còn lại. Tiếp đó là hệ thống các nội dung công việc, lưu trữ và bàn giao lại cho nhân sự mới (nếu có).
Những thứ có liên quan như tài sản, giấy tờ cũng được sắp xếp theo quy trình. Đặc biệt, chính bạn là người chia sẻ, hướng dẫn lại công việc cho người mới; trao đổi và trình bày với họ nắm rõ quy chế và cách xử lý công việc trong thời gian tới.
3. Tuân thủ hiệu lực hợp đồng lao động
Nếu rời đi không bao trước, không có đơn xin thôi việc và không nhận được sự đồng ý của công ty, bạn sẽ phải chịu trách nhiệm cho hành động của mình. Việc đơn phương chấm dứt hợp đồng mà chưa có sự chấp thuận, bạn sẽ phải thực hiện các nghĩa vụ như sau:
Không nhận được trợ cấp thôi việc.
Bạn phải bồi thường cho người sử dụng lao động từ ½ đến một tháng tiền lương.
Tùy theo từng loại hợp đồng bổ sung hay quy chế riêng từng doanh nghiệp, bạn có thể được yêu cầu hoàn trả toàn bộ chi phi đào tạo ban đầu.
Việc đơn phương chấm dứt hợp đồng khiến bạn có một “chấm đen” trong hồ sơ xin việc. Và đó là rào cản khiến bạn khó khăn trong việc tìm kiếm công việc mới.
Từ những phân tích trên cho thấy, mọi thứ đều phải tuân thủ các quy trình. Bạn cần thực hiện đầy đủ việc viết đơn xin nghỉ việc để để đảm bảo quyền lợi cũng như trách nhiệm của bản thân mình. Tất nhiên vẫn phải lưu tâm về một lý do xin nghỉ việc hợp lý.
Mẹo ứng xử “khôn khéo” khi viết đơn xin nghỉ việc
Như bạn đã biết, viết mẫu đơn xin thôi việc không phải chỉ dừng lại ở quy trình gửi đơn, chấp thuận rồi nghỉ một mạch. Mà nó cần quy trình và đôi khi là cả một nghệ thuật.
Việc khéo léo và tinh tế trong các thủ thuật viết đơn xin nghỉ việc sẽ cho thấy bạn là một nhân viên chuyên nghiệp. Hãy quan tâm và bỏ túi những cách thức dưới đây.
1. Suy nghĩ thận trọng trước khi quyết định gửi đơn
đơn xin nghỉ việc
Đây thật sự là một bước quan trọng. Bạn không thể thích thì nghỉ. Việc tùy hứng thể hiện bạn là người thiếu trách nhiệm. Hãy đặt ra các câu hỏi, sau đó cân nhắc trước khi đi đến quyết định viết đơn xin thôi việc.
Sau đây là một vài suy nghĩ và phán đoán bạn nên tham khảo:
Liệu bạn đã giải quyết hết những công việc còn lại chưa?
Bạn có chắc chắn tìm được việc mới sau khi nghỉ việc?
Lý do xin việc ấy liệu là nhất thời? Nó có tương xứng với những công sức bạn cống hiến hay không?
Ở môi trường làm việc mới, các chế độ phúc lợi, các kỹ năng, kiến thức mới bạn học được có giúp bạn nhanh chóng thăng tiến như kỳ vọng?
Rất nhiều thứ cần bạn suy nghĩ kỹ lưỡng. Do đó, bạn không thể đưa ra các quyết định một cách vội vàng. Hãy thật sự thận trọng khi đi quyết định rời đi. Khi đã thật sự lựa chọn được hướng đi, hãy dành tâm sức đầu tư cho lá đơn xin nghỉ việc một cách hoàn hảo. Nó không đơn giản chỉ là một tờ trình, mà đó còn là sự tôn trọng với chính tổ chức nhân sự của bạn.
2. Thời điểm rời đi rất quan trọng
Sau khi đã cân nhắc và có những quyết định, bạn nên quan tâm đến tình thế hiện tại của công ty.
Ví dụ như: công ty có đang thật sự ổn về nhân lực? Các chiến lược phát triển sản phẩm, dự án hoạt động, sự kiện thường niên có đang vào thời điểm nóng hay không? Nếu là một nhân viên thật sự có tâm, bạn phải nhìn nhận rõ vấn đề này. Bạn không nên rời đi nếu công ty rơi vào khủng hoảng khó khăn. Hãy nghĩ đến công ty dù đó chỉ là vài tháng tới!
Trước khi rời đi, đây có phải thời gian thích hợp để bạn bỏ đi những mâu thuẫn vốn có với sếp, đồng nghiệp? Thật sự đó là một suy nghĩ đúng đắn! Bạn nên cởi mở, tìm kiếm cơ hội để tháo gở những nút thắt bất đồng nảy sinh. Có thế như thế, khi “tốt nghiệp” môi trường làm việc cũ, bạn sẽ cảm thấy thoải mái hơn.
Đồng thời, đó cũng là cơ sở giúp nuôi dưỡng các mối qun hệ đẹp của bạn. Từ suy nghĩ đó, bạn có thể tự tin tìm kiếm công việc mới cũng như mong đợi về một chặng đường tươi đẹp, suôn sẻ hơn.
Cách viết mẫu đơn xin nghỉ việc chuẩn nhất
1. Phần mở đầu
Quốc hiệu, tiêu ngữ
Bạn cần phải triển khai viết quốc hiệu, tiêu ngữ trước khi đi vào chi tiết. Cụ thể như sau:
CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM
Độc lập – Tự do – Hạnh phúc
Tên đơn: Đon xin nghỉ việc, đơn xin thôi việc,… (Đơn nghỉ phép sẽ gắn với mục đích cụ thể tùy trường hợp thực tế).
Kính gửi: Đơn xin phép được gửi cho ai? Người viết đơn cần xác định rõ đối tượng cần gửi đơn. Đó có thể là cấp trên, người quản lý, Team Lead, trưởng nhóm,…
2. Phần nội dung trọng tâm mẫu đơn xin nghỉ việc
Phần này rất quan trọng và cần đảm bảo đầy đủ các nội dung như sau gồm:
– Các thông tin liên quan đến người viết đơn
– Mục đích của việc viết đơn xin nghỉ việc
– Lý do xin nghỉ phép: Các lý do phải thật sự chính đáng và hợp lý trong hoàn cảnh hiện thời của tổ chức/doanh nghiệp.
– Lời cam kết về sự thật và lởi cảm ơn
– Xác nhận minh chứng thông qua chữ ký (ký và ghi rõ họ tên)
Đặc biệt, một phần đáng lưu tâm nữa, bạn nên trình bày thêm những nội dung sau:
– Những kinh nghiệm, các giá trị bạn có được trong thời gian làm việc tại công ty
– Chia sẻ về quá trình trưởng thành của bạn
– Gửi lời cảm ơn và sự trân trọng với những ai đã giúp đỡ bạn
– Nhắc lại những ấn tượng về các cột mốc/dấu ấn khó quên của bạn
– Trình bày lý do rời đi một cách chân thật, có chiều sâu
– Nếu có thể, hãy đề cử các ứng viên thay thế phù hợp
Những lưu ý khi viết đơn xin nghỉ việc
Sau đây là những lưu ý sẽ thật sự giúp bạn có một lá đơn xin thôi việc thật sự thuyết phục.
Những tips cần quan tâm khi viết đơn xin thôi việc rất cần thiết.
1. Văn phong lịch sự
Thái độ quyết định tất cả. Điều này không bao giờ là sai. Khi viết mẫu đơn xin nghỉ việc, bạn cần có một thái độ tôn trọng, lịch sự. Điều đó được thể hiện qua văn phong trình bày, ngôn ngữ bạn sử dụng. Đừng quá phô trương các cảm xúc vào lá đơn mà hãy kiếm soát tốt nó.
2. Nội dung mô tả về lý do phải chi tiết
Lý do nghỉ việc. thôi việc là nội dung trọng tâm mà bạn muốn truyền tải đến cấp trên. Và dù là loại văn bản, giấy tờ dưới hình thức nào, nội dung đều phải được chú trọng.
Bên cạnh lý do hợp lý, cách trình bày rõ ràng, chân thật, bạn nên chia sẻ với người quản lý về thời gian mà bạn sẽ trở lại với công việc (trường hợp bạn tạm thời nghỉ việc). Đó được hiểu là lời cam kết mang dấu ấn uy tín; và trách nhiệm của bạn với công việc. Trong trường hợp đó, hãy linh hoạt để lại thông tin cá nhân, đề phòng những vấn đề phát sinh liên quan đến quyền lợi.
Tương tự, nếu bạn là cá nhân chịu trách nhiệm quản lý trực tiếp các dự án lớn, hãy nhanh chóng bàn giao. Công tác bàn giao cần được tiến hành lập tức và trong khoảng thời gian ngắn. Bạn phải đảm bảo cho dù thế nào, khi bạn rời đi, mọi quy trình vẫn được tiếp diễn. Đồng thời, chắc chắn không tạo ra sự thay đổi và ảnh hướng tiêu cực đến mọi người xung quanh bạn.
Làm gì để nghỉ việc chuyên nghiệp?
Chắc chắn rằng sau khi rời đi, việc bạn làm đầu tiên là tìm việc mới. Hãy cố gắng hoàn thiện một bộ hồ sơ xin việc để đảm bảo quá trình ấy diễn ra thuận lợi. Nếu là một cá nhân nghỉ việc chuyên nghiệp, bạn cần quan tâm đến những yếu tố xung quanh.
Cùng TopDev xem qua các thông tin dưới đây! Chúng đều là những khía cạnh nhỏ. Song, chúng có ích trong mối quan hệ với cách thức tổ chức/quản lý nhân sự.
1. Rời đi bí mật
Bí mật ở đây không phải bạn tự ý rời đi không viết mẫu đơn thôi việc. Mà nó hiểu là bạn không nên chia sẻ chúng cho những người bạn thân thiết.
Đặc biệt, trước khi tìm được công việc phù hợp mới, bạn lại không nên chia sẻ. Bởi đơn giản, việc bạn nghỉ việc có thể làm ảnh hưởng đến tâm trạng, suy nghĩ của những người xung quanh. Hệ quả tiêu cực hơn là khiến cho hiệu suất công việc của họ bị thụt lùi.
2. Hệ thống hóa và lưu lại những thứ bạn đã làm
Mọi bài học dù ở môi trường nào đều có giá trị. Nó đều có ích cho sự nghiệp phát triển riêng của bạn sau này. Vì thế, dù nghỉ việc, bạn vẫn phải có trách nhiệm lưu trữ hồ sợ, thông tin về các dự án bạn thực hiện.
Điều này vừa có lợi cho việc thiết lập tài liệu bàn giao cho nhân sự mới; vừa giúp bạn nhìn nhận lại những nỗ lực và thành quả thực tế trong hành trình dài vừa qua.
Những tựa sách nổi tiếng dành cho Software Developer – Phần 1
Tác giả: Andrew
Giới thiệu
Với hai bài viết được chia sẻ ở các phần trước, các Software Developer đã phần nào tìm được cho mình những nội dung tham khảo tốt nhất. Phần này sẽ chia sẻ với các dev phần còn lại của chuỗi các tựa sách nổi tiếng về phát triển phần mềm.
Chuỗi các tựa sách về kỹ năng Software Developer cho công việc build phần mềm
Những cuốn sách cho Software Developer được lựa chọn nhiều nhất
15. Introduction to Algorithms – Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein
Một số sách về thuật toán hiện có trên thị trường dù khá chặt chẽ nhưng không đầy đủ. Cuốn sách về các thuật toán này là sự kết hợp độc đáo giữa tính chặt chẽ và tính toàn diện. Nó bao gồm một loạt các thuật toán chuyên sâu, nhưng vẫn làm cho thiết kế và phân tích của chúng có thể tiếp cận với mọi cấp độ độc giả. Mỗi chương tương đối khép kín và có thể được sử dụng như một chủ đề nghiên cứu khá hiệu quả. Những nội dung được chia sẻ trong đó đã được giữ nguyên bản mà không làm mất đi độ sâu của nội dung hoặc tính chặt chẽ của toán học.
16. Agile Software Development: Principles, Patterns, and Practices – Robert C. “Uncle Bob” Martin
Agile Software Development được viết bởi một Software Developer nên toàn bộ nội dung của cuốn sách cũng chủ yếu liên quan đến vấn đề Software Developing. Nội dung cuốn sách bao gồm các phương pháp OOD, UML, Design Patterns, Agile và XP với mô tả chi tiết về một thiết kế phần mềm hoàn chỉnh cho các chương trình có thể tái sử dụng trong C++ và Java. Sử dụng cách tiếp cận thực tế, giải quyết vấn đề, nó chỉ ra cách phát triển một ứng dụng hướng đối tượng – từ giai đoạn đầu của phân tích, thông qua thiết kế cấp thấp và triển khai.
Cuốn sách bao gồm các phần: Tin học và Động lực học, Nguyên tắc thiết kế lớp học, Quản lý sự phức tạp, Nguyên tắc thiết kế bao bì, Phân tích và Thiết kế, Các mẫu và Giao cắt Mô hình. Giải thích các nguyên tắc của OOD, từng cái một, và sau đó tác giả chứng minh nội dung được giải thích với nhiều ví dụ, thiết kế hoàn toàn được làm việc kỹ lưỡng và nghiên cứu điển hình. Thảo luận chi tiết các phương pháp thiết kế và phát triển phần mềm lớn.
17. CODE: The Hidden Language of Computer Hardware and Software – Charles Petzold
Trong CODE các tác giả cho chúng ta thấy những cách khéo léo mà các lập trình viên có thể vận dụng ngôn ngữ và phát minh ra các phương tiện giao tiếp mới với nhau. Và thông qua CODE, chúng ta cũng sẽ nhận thấy sự khéo léo này và sự bắt buộc giao tiếp của chính con người chúng ta đã thúc đẩy những đổi mới công nghệ trong hai thế kỷ qua như thế nào.
Sử dụng các vật dụng hàng ngày và các hệ thống ngôn ngữ quen thuộc như chữ nổi Braille và mã Morse, tác giả Charles Petzold đã tạo nên một câu chuyện sáng tạo cho bất kỳ ai từng thắc mắc về cách hoạt động đầy khó hiểu bên trong máy tính và các loại máy thông minh khác.
Tham khảo thêm nhiều đầu sách kỹ năng giúp dev nâng cao tay nghề
18. Sách cho Software Developer “The Art of Computer Programming” – Donald Knuth
Đây là cuốn sách kinh điển đã được xuất bản cách đây vài thập kỷ nhưng đến thời điểm hiện tại, tác phẩm vẫn giữ được tính hiệu quả của mình với các nội dung đầy chất lượng. Một trong những điểm mạnh nhất của cuốn sách là bộ sưu tập các bài toán cực kỳ ấn tượng đi kèm với mỗi chương. Tác giả đã chọn các vấn đề một cách cẩn thận và lập chỉ mục toàn bộ nội dung theo độ khó. Giải quyết một số lượng đáng kể các vấn đề này sẽ giúp bạn có được sự hiểu biết vững chắc về các vấn đề xung quanh chủ đề đã cho. Hơn nữa, các bài tập có một loạt các bài toán kinh điển.
19. Clean Architecture: A Craftsman’s Guide to Software Structure and Design – Robert C. “Uncle Bob” Martin
Cuốn sách này sẽ giúp bạn tìm hiểu công việc mà kiến trúc sư phần mềm cần đạt được là những gì, và các nguyên tắc cũng như cách thực hiện cốt lõi để đạt được điều đó. Người viết cần nắm vững các nguyên tắc thiết kế phần mềm cần thiết để giải quyết chức năng, tách thành phần và quản lý dữ liệu. Xem cách các mô hình lập trình áp đặt kỷ luật bằng cách hạn chế những gì nhà phát triển có thể làm cũng như hiểu điều gì cực kỳ quan trọng và điều gì chỉ đơn thuần là “chi tiết”.
Ngoài ra, với Clean Architecture, các tác giả sẽ triển khai các cấu trúc cấp cao, tối ưu cho web, cơ sở dữ liệu, máy khách dày, bảng điều khiển và các ứng dụng nhúng, xác định ranh giới và lớp thích hợp, đồng thời tổ chức các thành phần và dịch vụ. Dựa vào đó, bạn sẽ xem được lý do tại sao thiết kế và kiến trúc gặp lỗi và cách ngăn chặn (hoặc sửa chữa) những lỗi này như thế nào.
20.Sách cho Software Developer “Patterns of Enterprise Application Architecture” – Martin Fowler
Cuốn sách này thực sự được nhiều người dùng đánh giá là cuốn sách có nội dung hai trong một. Phần đầu tiên của Patterns of Enterprise Application Architecture là một hướng dẫn ngắn về phát triển ứng dụng doanh nghiệp, bạn có thể đọc từ đầu đến cuối để hiểu phạm vi bài học của cuốn sách. Phần tiếp theo, cũng là phần chính trong toàn bộ nội dung của cuốn sách, là tài liệu tham khảo chi tiết về bản thân các mẫu. Mỗi mẫu cung cấp thông tin sử dụng và triển khai, cũng như các ví dụ mã chi tiết trong Java hoặc C#. Toàn bộ cuốn sách cũng được minh họa phong phú bằng các sơ đồ UML để giải thích thêm về các khái niệm.
Khi tìm hiểu về những thông tin được cung cấp trong cuốn sách này, bạn sẽ có kiến thức cần thiết để đưa ra các quyết định quan trọng trong việc xây dựng một ứng dụng doanh nghiệp và các mô hình đã được chứng minh để sử dụng khi xây dựng chúng.
Chuỗi bài viết này là thông tin tổng hợp gần như đầy đủ như cuốn sách về Software Developer phổ biến và hiệu quả nhất ở thời điểm hiện tại. Tìm đọc các nguồn này chắc chắn sẽ mang đến cho bạn những kỹ năng làm việc hiệu quả hơn trong thời gian tới.
Mình vừa làm seminar kết thúc môn học Cấu trúc dữ liệu và giải thuật, mình sẽ chia sẻ với các bạn về seminar của mình. Đề tài của mình: Đánh giá hiệu suất các thuật toán tìm kiếm và so sánh.
Bình thường khi học, độ phức tạp về thời gian của các thuật toán mà các bạn được giới thiệu đều là Big O notation, nhìn vào đó các bạn có thể biết được thuật toán nhanh hay chậm. Tuy nhiên, các bạn lại không biết được thuật toán nhanh hay chậm hơn như thế nào. Do đó mình muốn tạo ra chương trình thực hiện các thuật toán và đo thời gian thực hiện, từ đó các bạn có thể dễ dàng so sánh và thấy được hiệu suất của thuật toán.
Dù mỗi máy có tốc độ xử lý khác nhau, hiệu suất thuật toán phụ thuộc vào rất nhiều yếu tố, tuy nhiên, các thuật toán cùng thực hiện trên cùng một máy, tức là cùng 1 điều kiện, vậy nên chúng ta vẫn có thể thấy được sự chênh lệch hiệu suất của các thuật toán.
Mình quyết định sử dụng WPF để có thể dễ dàng custom giao diện đẹp hơn.
Tính năng
Một số tính năng của phần mềm mình viết:
Tạo dãy số ngẫu nhiên
Lưu vào file
Load dãy số từ file
Tìm kiếm theo 3 thuật toán
Sắp xếp theo 7 thuật toán
Xem kết quả thời gian thực hiện thuật toán
Xem kết quả dãy sau khi sắp xếp
Xem code thuật toán bằng C++
Demo
Một số screenshot Seminar của mình:
Source code
Các bạn có thể xem code seminar của mình trên Github. Có một lưu ý nhỏ là thư mục ViewCode phải được đặt cùng cấp với file exe thì tính năng View code mới có thể lấy code ra được.
Tổng kết
Seminar này mình chỉ làm sơ sài thôi, code cũng không clean, tổ chức chưa tốt lắm, các bạn tham khảo cho vui thôi nha!
Bài viết được sự cho phép của tác giả Nguyễn Việt Hưng
Làm sao để in ra từ 1 đến 10 bằng hàm đệ quy?
I. Hàm đệ quy
Recursive function (hàm đệ quy) là function mà nó tự gọi chính nó. Phần định nghĩa function trông như thế này:
deffoo():dosomething()foo()# gọi chính nómaybedosomething()returnotherthing
Recursion là một lối suy nghĩ, một cách lập trình rất phổ biến trong functional programming (lập trình hàm) nhưng ở thế giới còn lại, nó không thực sự phổ biến hay có vẻ quen thuộc. Quan điểm về viết recursive function cũng khác nhau, có người bảo dễ, có người mãi không hiểu gì. Và nếu bạn thuộc nhóm không hiểu gì, thì không phải do bạn dốt, chỉ là chưa quen thôi.
Đề bài: Cho số nguyên dương N, viết function in ra màn hình từ 1 đến N.
Lời giải:
Cách bình thường:
deflprint(n):''' Prints from 1 to n the loop way '''foriinrange(1,n+1):print(i)lprint(3)
Còn đây cách đệ quy:
defrprint(n):''' Prints from 1 to n recursive way '''ifn==0:returnelse:rprint(n-1)print(n)rprint(3)
Output:
1
2
3
Nếu bạn không hiểu đoạn code trên thực sự làm gì qua từng bước, hãy xem phiên bản chỉnh sửa một chút để in ra giải thích sau:
INPUT=10defrprint2(n):pad=3*' '*(INPUT-n)print('%sInside function with %d'%(pad,n))ifn==0:returnelse:print('%s calling rprint2(%d)'%(pad+'|'+'_',n-1))rprint2(n-1)print('%s| printing %d'%(pad,n))print(n)returnrprint2(INPUT)
Output:
Inside function with 10
|_ calling rprint2(9)
Inside function with 9
|_ calling rprint2(8)
Inside function with 8
|_ calling rprint2(7)
Inside function with 7
|_ calling rprint2(6)
Inside function with 6
|_ calling rprint2(5)
Inside function with 5
|_ calling rprint2(4)
Inside function with 4
|_ calling rprint2(3)
Inside function with 3
|_ calling rprint2(2)
Inside function with 2
|_ calling rprint2(1)
Inside function with 1
|_ calling rprint2(0)
Inside function with 0
| printing 1
1
| printing 2
2
| printing 3
3
| printing 4
4
| printing 5
5
| printing 6
6
| printing 7
7
| printing 8
8
| printing 9
9
| printing 10
10
Hãy đọc từ trên xuống dưới, chậm rãi, để hiểu chuyện gì đã xảy ra. Nếu vẫn chưa hiểu?
Hãy đọc lại từ đầu!
Ví dụ trên chỉ nhằm minh hoạ recursive function làm việc như thế nào, chứ không có lợi ích gì khi viết hàm recursive trong trường hợp này.
Recursive function sẽ trở nên rất hữu dụng nếu vấn đề được định nghĩa theo cách đệ quy (các hàm toán học), giải bài toán Tháp Hà Nội, hay chỉ đơn giản là muốn tiến gần hơn một bước đến Functional programming.
Bài viết được sự cho phép của tác giả Kien Dang Chung
Bất kể hệ thống website nào cũng có người dùng và đi kèm với nó là việc xác thực (authentication) và phân quyền (authorization) với từng người dùng. Xác thực trong Laravel là khá đơn giản với Laravel Authentication, chúng ta cũng có thể tận dụng các hệ thống khác như mạng xã hội để xác thực, ví dụ xác thực người dùng bằng Facebook, Google, Twitter… Bên cạnh đó, chúng ta cũng rất cần phân quyền cho người dùng để đảm bảo các vấn đề về bảo mật và tuân thủ các chính sách từng hệ thống. Ví dụ như có những người dùng được phép chỉnh sửa hoặc xóa một tài nguyên nhưng cũng có những người dùng chỉ được phép đọc thông tin. Từ phiên bản Laravel 5.1 trở về trước, công việc này phải thực hiện thông qua các gói ACL (Access Control List) như Entrust, Sentinel hay Laravel-ACL thì hiện nay Laravel đã có hỗ trợ trực tiếp trong core của framework. Với việc sử dụng các gói ACL ở ngoài, các quyền cho người dùng chỉ là các cờ, nếu muốn các nghiệp vụ phức tạp trong phân quyền, bạn sẽ rất khó khăn và phải đưa vào Controller. Sử dụng Laravel Gate tránh được một số các nhược điểm của việc sử dụng các gói ACL ngoài như sau:
Sử dụng Laravel Gate cho bạn sự tự do, bạn có thể sử dụng cho các trường hợp cực phức tạp tùy ý do nó không bắt buộc phải implement trong các model.
Bạn có hoàn toàn tự chủ về các chính sách phân quyền, với Laravel Gate các xử lý truy cập có thể tách biệt với các xử lý về nghiệp vụ, loại bỏ sự phụ thuộc và code trong các controller dễ đọc hơn.
Gate và Policy giống như Route với Controller, Gate cũng cấp một giải pháp dựa trên Closure để phân quyền trong khi các policy giống với controller nhóm các logic nghiệp vụ liên quan đến Model hoặc các tài nguyên. Chúng ta cùng tìm hiểu về Gate trước khi tìm hiểu về Policy. Phần lớn các ứng dụng sẽ sử dụng cả Gate và Policy, Gate được áp dụng cho các hành động không liên quan đến Model hoặc các tài nguyên như việc truy nhập vào trang quản trị dashboard. Ngược lại, policy được sử dụng khi bạn muốn cho phép một hành động truy nhập vào một model hoặc nguồn tài nguyên.
Gate là các Closure được xác định nếu một người dùng được xác thực để thực hiện một hành động, nó được định nghĩa trong App\Providers\AuthServiceProvider sử dụng facade Gate. Gate luôn nhận một thực thể user là tham số thứ nhất và có thể có các tham số tùy chọn khác như Eloquent Model:
Mặc định view, create, update và delete được định nghĩa. Bạn có thể override các khả năng này bằng cách truyền vào một mảng như là tham số thứ 3 cho phương thức resource. Key của mảng này định nghĩa tên khả năng trong khi giá trị định nghĩa tên phương thức.
Phân quyền Để phân quyền thực hiện một hành động, bạn có thể sử dụng các phương thức allows và denies, chú ý rằng bạn không cần truyền người dùng đã được xác thực vào các phương thức này. Laravel sẽ tự động xử lý việc đó trong các gate Closure:
if(Gate::allows('update-post',$post)){ // The current user can update the post...
}if(Gate::denies('update-post',$post)){ // The current user can't update the post...
}
Nếu bạn muốn xác định một người dùng nào đó có được phân quyền để thực hiện một hành động hay không, bạn có thể sử dụng phương thức forUser trên facade Gate:
if(Gate::forUser($user)->allows('update-post',$post)){ // The user can update the post...
}if(Gate::forUser($user)->denies('update-post',$post)){ // The user can't update the post...
}
Policy
Tạo policy
Policy là các class quản lý logic trong phân quyền liên quan đến một Model hoặc tài nguyên nào đó. Ví dụ, nếu ứng dụng của bạn là một blog, bạn có thể có một model Post và một policy là PostPolicy để phân quyền các hành động người dùng như tạo hay cập nhật các bài viết. Bạn có thể tạo ra một policy bằng cách sử dụng câu lệnh Artisan make:policy, các policy được tạo ra sẽ được đặt trong thư mục app\Policies. Nếu thư mục này không tồn tại trong project, Laravel sẽ tự động tạo nó cho bạn:
php artisan make:policy PostPolicy
Câu lệnh make:policy sẽ sinh ra một class policy rỗng, nếu bạn muốn sinh ra một CRUD policy bạn cần thêm tham số –model khi thực thi câu lệnh artisan:
php artisan make:policy PostPolicy --model=Post
Đăng ký Policy
Một policy muốn sử dụng cần được đăng ký, AuthServiceProvider được đưa vào trong project Laravel chứa một thuộc tính policies để map Eloquent model với các policy tương ứng. Đăng ký một policy sẽ chỉ dẫn cho Laravel policy nào sẽ được sử dụng để phân quyền hành động cho model nào:
<?phpnamespaceApp\Providers;useApp\Post;useApp\Policies\PostPolicy;useIlluminate\Support\Facades\Gate;useIlluminate\Foundation\Support\Providers\AuthServiceProvideras ServiceProvider;classAuthServiceProviderextendsServiceProvider{/**
* The policy mappings for the application.
*
* @var array
*/protected$policies=[Post::class=>PostPolicy::class,];/**
* Register any application authentication / authorization services.
*
* @return void
*/publicfunctionboot(){$this->registerPolicies(); //
}}
Logic nghiệp vụ trong Policy
Phương thức Policy Khi Policy được đăng ký, bạn có thể thêm các phương thức cho mỗi hành động cần cấp quyền. Ví dụ, định nghĩa phương thức update trên PostPolicy để xác định một user có thể cập nhật một thực thể Post. Phương thức update sẽ nhận được một User và Post như là tham số và nó trả về true hoặc false để nhận diện xem người dùng này có được phân quyền để cập nhật Post không? Trong ví dụ dưới đây, chỉ có người dùng đã viết bài mới có quyền cập nhật bài viết
<?phpnamespaceApp\Policies;useApp\User;useApp\Post;classPostPolicy{/**
* Determine if the given post can be updated by the user.
*
* @param \App\User $user
* @param \App\Post $post
* @return bool
*/publicfunctionupdate(User $user, Post $post){return$user->id===$post->user_id;}}
Bạn có thể tiếp tục định nghĩa các phương thức khác trên policy này nếu cần phân quyền cho các hành động. Ví dụ, bạn có thể định nghĩa phương thức view hoặc delete để phân quyền các hành động Post khác và nhớ rằng tên các phương thức trong policy là hoàn toàn bạn có thể đặt thoải mái nếu thích.
Route Model Binding
Có những phương thức policy chỉ nhận người dùng được xác thực hiện tại và không cần một thực thể của một Model. Tình huống này dùng khi phân quyền một hành động create. Ví dụ, nếu bạn tạo một blog, bạn có thể muốn kiểm tra nếu một người dùng có được phân quyền để tạo một post bất kỳ không. Khi định nghĩa phương thức trong policy nó sẽ không nhận một thực thể của Model, như phương thức create, nó sẽ không nhận một thực thể của model. Thay vào đó, bạn nên định nghĩa phương thức chỉ với người dùng đã được xác thực.
/**
* Determine if the given user can create posts.
*
* @param \App\User $user
* @return bool
*/publicfunctioncreate(User $user){ //
}
Policy Filter
Với người dùng hiện tại, bạn muốn cấp quyền thực hiện các hành động trong một chính sách, để thực hiện bạn định nghĩa phương thức before trong policy. Phương thức before sẽ thực thi trước bất kỳ phương thức nào trong policy, nó cho bạn cơ hội để cho phép thực hiện hành động trước khi phương thức của policy mong muốn được gọi. Tính năng này rất thông dụng để cho phép các administrator có thể thực hiện bất kỳ hành động nào:
Nếu bạn muốn một user không được phép thực hiện bất kỳ gì bạn chỉ cần trả về false trong phương thức before. Nếu null được trả về, việc cấp quyền sẽ được tiếp tục trong phương thức policy.
3. Cho phép thực hiện hành động sử dụng Policy
Thông qua User Model Model User được tạo sẵn trong project Laravel chứa hai phương thức có sẵn là can và cant. Phương thức can nhận hành động bạn muốn cấp phép và model liên quan. Ví dụ, để xác định một người dùng được phép cập nhật model Post không?
if($user->can('update',$post)){ //
}
Thực hành Laravel Authorization
Chúng ta cùng xem xét một ví dụ về phân quyền trong một tờ báo điện tử bao gồm hai chức danh là phóng viên và biên tập viên.
Phóng viên có thể viết một bài báo mới
Phóng viên có thể cập nhật nội dung bài báo của họ.
Biên tập viên có thể cập nhật nội dung bài báo.
Biên tập viên có thể phát hành bài báo.
Như vậy phóng viên không thể tự phát hành bài báo và biên tập viên không thể tạo ra bài báo mới mà chỉ có quyền cập nhật và xuất bản. Chúng ta sẽ từng bước thiết kế và phát triển ứng dụng web này, nó sẽ giúp bạn hiểu cạn kẽ về Laravel Authorization.
Cài đặt môi trường Laravel
Cài đặt môi trường Laravel rất đơn giản, bạn tham khảo bài Cài đặt Laravel dễ dàng với Laragon (trong bài này sẽ lấy tên project là allaravel nhé). Tiếp theo, chúng ta thực hiện cài đặt xác thực với Laravel Authentication. Đây là những phần rất cơ bản của Laravel, bạn nên làm quen vì hầu hết các dự án mới sẽ bắt đầu bằng bước này. Kiểm tra xem môi trường hoạt động tốt chưa, mở đường dẫn http://allaravel.dev.
Tạo database, dữ liệu test với Laravel Migrate và Laravel Seeding
Việc đầu tiên của dự án báo điện tử là thiết kế database, chúng ta sẽ có 4 bảng như sau:
Đầu tiên, chúng ta sử dụng câu lệnh artisan để tạo ra model Post kèm theo với controller PostController và file migrate bằng cách sử dụng các tùy chọn -m và -c.
php artisan make:model Post -m -c
Với câu lệnh này chúng ta có:
Model Post trong file app\Post.php.
Post Controller trong file app\Http\Controllers\PostController.php.
File migrate nằm trong databases\migrations\yyyy_mm_dd_xxxxxx_create_post_table.php.
Xử lý file migrate để tạo bảng post trong cơ sở dữ liệu, thiết lập các trường của bảng post như sau:
<?phpuseIlluminate\Support\Facades\Schema;useIlluminate\Database\Schema\Blueprint;useIlluminate\Database\Migrations\Migration;classCreatePostsTableextendsMigration{/**
* Run the migrations.
*
* @return void
*/publicfunctionup(){Schema::create('posts',function(Blueprint $table){$table->increments('id');$table->string('title');$table->string('slug')->unique();$table->text('body');$table->boolean('published')->default(false);$table->unsignedInteger('user_id');$table->timestamps();$table->foreign('user_id')->references('id')->on('users');});}/**
* Reverse the migrations.
*
* @return void
*/publicfunctiondown(){Schema::dropIfExists('posts');}}
Tiếp đến chúng ta tạo model Role kèm theo controller và file migrate:
php artisan make:model Role -m -c
Tạo các trường cho bảng roles với file migrate databases\migrations\yyyy_mm_dd_xxxxxx_create_roles_table.php:
<?phpuseIlluminate\Support\Facades\Schema;useIlluminate\Database\Schema\Blueprint;useIlluminate\Database\Migrations\Migration;classCreateRolesTableextendsMigration{/**
* Run the migrations.
*
* @return void
*/publicfunctionup(){Schema::create('roles',function(Blueprint $table){$table->increments('id');$table->string('name');$table->string('slug')->unique();$table->jsonb('permissions')->default('{}');$table->timestamps();});}/**
* Reverse the migrations.
*
* @return void
*/publicfunctiondown(){Schema::dropIfExists('roles');}}
Chú ý: trường permission chúng ta sẽ chứa một dữ liệu json thay vì tách ra thành một bảng riêng. Tiếp theo là bảng role_users chỉ cần tạo bảng do đó sử dụng câu lệnh artisan make:migrate
và định nghĩa các trường của bảng role_users trong file migrate databases\migrations\yyyy_mm_dd_xxxxxx_create_role_users_table
<?phpuseIlluminate\Support\Facades\Schema;useIlluminate\Database\Schema\Blueprint;useIlluminate\Database\Migrations\Migration;classCreateRoleUsersTableextendsMigration{/**
* Run the migrations.
*
* @return void
*/publicfunctionup(){Schema::create('role_users',function(Blueprint $table){$table->unsignedInteger('user_id');$table->unsignedInteger('role_id');$table->timestamps();$table->unique(['user_id','role_id']);$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');});}/**
* Reverse the migrations.
*
* @return void
*/publicfunctiondown(){Schema::dropIfExists('role_users');}}
Thiết kế model map từ database sang class
Trong phần 4.1 chúng ta đã cài đặt phần xác thực cho Laravel, nó tạo ra bảng user, model User tuy nhiên model này chưa có phần phân quyền. Chúng ta sẽ thêm hai phương thức cho model User:
hasAccess(): kiểm tra xem người dùng có quyền thực hiện một hành động nào đó không.
inRole(): kiểm tra xem một người dùng có thuộc về một chức danh nào đó không.
<?phpnamespaceApp;useIlluminate\Notifications\Notifiable;useIlluminate\Foundation\Auth\Useras Authenticatable;classUserextendsAuthenticatable{useNotifiable;protected$fillable=['name','email','password',];protected$hidden=['password','remember_token',];publicfunctionroles(){return$this->belongsToMany(Role::class,'role_users');}/**
* Checks if User has access to $permissions.
*/publicfunctionhasAccess(array$permissions): bool
{ // check if the permission is available in any role
foreach($this->rolesas$role){if($role->hasAccess($permissions)){returntrue;}}returnfalse;}/**
* Checks if the user belongs to role.
*/publicfunctioninRole(string $roleSlug){return$this->roles()->where('slug',$roleSlug)->count()==1;}}
Chúng ta sẽ tạo dữ liệu kiểm thử trong file vừa tạo ra databases\seeds\RolesSeeder.php như sau:
<?phpuseIlluminate\Database\Seeder;useApp\Role;classRolesSeederextendsSeeder{/**
* Run the database seeds.
*
* @return void
*/publicfunctionrun(){$author=Role::create(['name'=>'Phóng viên','slug'=>'author','permissions'=>['post.create'=>true,]]);$editor=Role::create(['name'=>'Biên tập viên','slug'=>'editor','permissions'=>['post.update'=>true,'post.publish'=>true,]]);}}
Role author sẽ sử dụng cho phóng viên còn role editor sẽ sử dụng cho biên tập viên. Tiếp đến là databases\seeds\UsersSeeder.php:
<?phpuseIlluminate\Database\Seeder;useApp\User;useApp\Role;classUsersSeederextendsSeeder{/**
* Run the database seeds.
*
* @return void
*/publicfunctionrun(){$author=Role::where('slug','author')->first();$editor=Role::where('slug','editor')->first();$user1=User::create(['name'=>'Phóng viên 1','email'=>'pv1@allaravel.dev','password'=>bcrypt('123456')]);$user1->roles()->attach($author);$user2=User::create(['name'=>'Phóng viên 2','email'=>'pv2@allaravel.dev','password'=>bcrypt('123456')]);$user2->roles()->attach($author);$user3=User::create(['name'=>'Biên tập viên 1','email'=>'btv1@allaravel.dev','password'=>bcrypt('123456')]);$user2->roles()->attach($editor);}}
và databases\seeds\PostsSeeder.php:
<?phpuseIlluminate\Database\Seeder;useApp\User;useApp\Post;classPostsSeederextendsSeeder{/**
* Run the database seeds.
*
* @return void
*/publicfunctionrun(){$author1=User::where('email','pv1@allaravel.dev')->first();$author2=User::where('email','pv2@allaravel.dev')->first();$faker=Faker\Factory::create();for($i=0;$i<10;$i++){$title=$faker->sentence($nbWords=6,$variableNbWords=true);$post=Post::create(['title'=>$title,'body'=>$faker->text($maxNbChars=1000),'slug'=>str_slug($title),'published'=>rand(0,1),'user_id'=>$author1->id]);$title=$faker->sentence($nbWords=6,$variableNbWords=true);$post=Post::create(['title'=>$title,'body'=>$faker->text($maxNbChars=1000),'slug'=>str_slug($title),'published'=>rand(0,1),'user_id'=>$author2->id]);}}}
Chú ý, gọi đến các Seeder này trong databases\seeds\DatabaseSeeder.php:
<?phpuseIlluminate\Database\Seeder;classDatabaseSeederextendsSeeder{/**
* Run the database seeds.
*
* @return void
*/publicfunctionrun(){$this->call(\RolesSeeder::class);$this->call(\UsersSeeder::class);$this->call(\PostsSeeder::class);}}
Ok, vậy là phần chuẩn bị khung cho cơ sở dữ liệu và đưa vào dữ liệu kiểm thử đã xong, để thực hiện các công việc này trên database sử dụng lệnh artisan migrate với tùy chọn –seed
php artisan migrate --seed
Thiết lập chính sách phân quyền
Câu lệnh make:policy giúp tạo ra một class policy để chứa các logic về phân quyền. Trong ví dụ hiện tại, chúng ta có model Post tương ứng với class PostPolicy để phân quyền các hành động của người dùng như tạo mới bài viết, cập nhật bài viết.
php artisan make:policy PostPolicy --model=Post
Policy created successfully.
Thiết lập các chính sách truy cập trong file app\Policies\PostPolicy.php
<?phpnamespaceApp\Policies;useApp\User;useApp\Post;useIlluminate\Auth\Access\HandlesAuthorization;classPostPolicy{useHandlesAuthorization;publicfunctionview(User $user, Post $post){ //
}publicfunctioncreate(User $user){return$user->hasAccess(['post.create']);}publicfunctionupdate(User $user, Post $post){return$user->hasAccess(['post.update'])or$user->id==$post->user_id;}publicfunctiondelete(User $user, Post $post){ //
}publicfunctionpublish(User $user){return$user->hasAccess(['post.publish']);}publicfunctiondraft(User $user){return$user->inRole('editor');}}
Đăng ký chính sách với hệ thống trong app\Providers\AuthServiceProvider.php:
<?phpnamespaceApp\Providers;useIlluminate\Support\Facades\Gate;useIlluminate\Foundation\Support\Providers\AuthServiceProvideras ServiceProvider;useApp\Policies\PostPolicy;classAuthServiceProviderextendsServiceProvider{/**
* The policy mappings for the application.
*
* @var array
*/protected$policies=['App\Model'=>'App\Policies\ModelPolicy',];/**
* Register any authentication / authorization services.
*
* @return void
*/publicfunctionboot(){$this->registerPolicies();Gate::resource('post',PostPolicy::class);Gate::define('post.publish',PostPolicy::class.'@publish');Gate::define('post.draft',PostPolicy::class.'@draft');}}
Định nghĩa các route liên quan đến post và có kiểm tra quyền truy xuất trong routes\web.php
Trong phần này, chúng ta sẽ xử lý các công việc còn lại là tạo ra các view và chuẩn bị dữ liệu cho các view này thông qua controller. Trong phần 4.2 khi tạo ra model Post chúng ta cũng đã tạo ra PostController, thực hiện xử lý logic cho từng route trước khi định tuyến đến view.
Các view cho việc tạo, cập nhật bài viết và các hành động khác như danh sách bài viết chưa đăng, hiển thị chi tiết app\resources\views\posts\index.blade.php
@extends('layouts.app')
@section('content')<div class="container"><div class="row"><div class="col-md-12"><h2>Bạn không có quyền truy nhập đường dẫn này.</h2></div></div></div>
@endsection
Chạy thử ứng dụng
Khi vào màn hình trang chủ http://allaravel.dev, chúng ta sẽ thấy một số các bài viết đã được xuất bản
Khi đăng nhập vào bằng user pv1@allaravel.dev và pv2@allaravel.dev chúng ta thấy các tài khoản này chỉ được tạo mới và cập nhật bài viết.
Phóng viên 1 có thể chỉnh sửa bài viết có id 32 và sửa đường dẫn thành http://allaravel.dev/posts/publish/32 để xuất bản bài viết nhưng do Phóng viên 1 không có quyền xuất bản do đó sẽ gặp thông báo lỗi “Bạn không có quyền truy nhập đường dẫn này”.
Đăng nhập vào user Biên tập viên 1, chúng ta thấy user này không có quyền tạo bài viết mới.
Selenium-Grid là một chế độ thực thi kiểm thử của Selenium mà ban đầu chỉ hỗ trợ cho Selenium RC như mình có nói ở bài trước. Tuy nhiên, sau này, đội ngũ phát triển của Selenium đã phát triển công cụ này cho cả Selenium WebDriver (Selenium 2).
Selenium-Grid cho phép người dùng thực thi kiểm thử trên nhiều máy khác nhau với nhiều trình duyệt khác nhau. Đặc biệt hơn nữa là, Selenium-Grid còn cho phép chúng ta thực thi kiểm thử với chế độ phân tán.
Để thiết lập môi trường cho Selenium-Grid, đâu tiên chúng ta cần cài đặt Java. Để kiểm tra PC có Java hay không, chúng ta có thể chạy câu lệnh này ở Command Line:
java –version
Nếu máy các bạn có Java thì version hiện tại của Java sẽ được trả về. Các bạn cố gắng lấy version mới nhất của Java nha.
Selenium Server
Kế tiếp là chúng ta cần có Selenium Server. Các bạn có thể download phiên bản mới nhất của Selenium Server ở đây.
Sau khi download Selenium Server về máy, chúng ta cần kiểm tra để chắc chắn rằng chương trình này có thể được sử dụng trên PC của chúng ta.
java –jar selenium-server-standalone-*.jar
Nếu mọi chuyện OK, INFO: Launching a standalone server sẽ được trả về.
Hub và Node
Hub
Hub là trung tâm phân phối nơi mà chúng ta gửi lệnh đến.
Chúng ta chỉ có một và chỉ một Hub trong một Selenium-Grid
Hub chỉ có thể được thiết lập trên một máy
Máy được thiết lập cho Hub là nơi kịch bản kiểm thử được thực thi, nhưng mà chúng ta sẽ thất trình duyện chạy ở trên Node
Node
Node là nơi các trình duyện chạy các kịch bản kiểm thử mà chúng ta đưa vào hub
Có thể có nhiều node trong một Grid
Node có thể được thiết lập trên nhiều máy với nhiều trình duyệt khác nhau
Bạn đã bao giờ tìm hiểu về phong cách hợp tác cá nhân chưa? Nó thật sự là một điều quan trọng đấy. Tại sao? Vì hiệu quả của sự kết nối, tương tác trực tiếp, làm việc nhóm đều chịu sự chi phối của phong các hợp tác.
Phong cách hợp tác là yếu tố cần khai thác trước khi bạn tiến hành thực hiện công việc, đặc biệt là giải quyết nhiệm vụ với tư cách là một nhóm. Mỗi phong cách hợp tác sẽ thể hiện các đặc trưng dấu ấn về cá tính của từng cá nhân. Đó là cơ sở để bạn có thể lựa chọn ra những người cộng sự phù hợp nhất.
Cùng TopDev tìm ra phong cách của riêng bạn thông qua bài viết sau nhé.
Người “độc tài”
Nếu thuộc nhóm này, bạn sẽ dễ dàng nhận ra các lợi ích tốt nhất cho dự án của bạn. Và tất nhiên, bạn rất chủ động trong việc lập kế hoạch; muốn chia sẻ và trình bày cụ thể chúng với những cộng sự của bạn.
Bạn là người có một sự tập trung cực kỳ cao, luôn theo sát các thông số báo cáo mô tả tiến trình hoạt đồng. Đồng thời, bạn chủ động tìm kiếm các thông tin cập nhật từ nhóm. Do có sự kỳ vọng quá lớn, đôi lúc bạn cảm thấy một dự án nào đó có thể bị ảnh hưởng nếu thiếu đi sự cảnh giác của bạn. Một freelancer IT là người biết vận dụng nhiều kỹ năng. Và tất nhiên, năng lực tập trung tuyệt đối là rất quan trọng.
Đồng ý rằng việc giám sát và quản lý chặt chẽ các đầu công việc là một điều tốt. Đó cũng là cách để hạn chế những sai sót có thể xảy ra. Và bạn cũng cho thấy được, bạn thật sự là một cá nhân có trách nhiệm với nhóm của mình. Tuy nhiên, bạn nên thảo luận, đánh giá và tạo cơ hội cho các thành viên trong nhóm phản hồi.
Có như vậy, một chiến dịch sẽ được theo dõi chặt chẽ và hiệu quả hơn do được đảm bảo về tính minh bạch, tính thống nhất về quan điểm thiết lập quy trình giải quyết công việc.
Người “tích trữ”
Với phong cách cộng tác này, bạn thuộc tuýp người thích ghi chú lại một cách chi tiết, lưu trữ và thống kê thông tin về từng giai đoạn, tiến độ phát triển. Để tối ưu hóa, bạn đã có thể lưu tất cả các email, tạo liên kết. Ngoài ra, bạn có thể cập nhập, chỉnh sửa – bổ sung các nội dung có liên quan đến dự án.
Đặc biệt, với cách phân bổ hợp lý, không quá khó để bạn tra cứu các thông tin. Chính điều này đã giúp nhóm của bạn sở hữu nguồn tư liệu đa dạng hơn. Thế nhưng, bạn không nên quá tập trung vào việc quản lý dữ liệu của riêng bạn. Hãy quan tâm đến các đồng đội vì các bạn là một team.
Người “phân tích”
Với khả năng tư duy nhanh nhạy và nhiều đa dạng về góc nhìn, bạn tự thúc đẩy bản thân muốn tìm hiểu và thực hiện khai thác, phân tích dự án một cách chi tiết. Vì là phân tích nên bạn thường sử dụng những kiến thức được minh chứng cụ thể về số liệu. Do vậy, hầu như trong mọi trường hợp, bạn đều nhận được sự tin tưởng từ mọi người. Ngược lại, bạn cũng sẽ phản bác các quan điểm thiếu xác thực, chưa đảm bảo về những minh chứng.
Nếu bạn phát hiện ra một vấn đề nào đó, đừng ngần ngại mà trao đổi mối quan tâm của bạn với các đồng đội của mình. Đừng tự ý xử lý một mình! Bình tĩnh thảo luận và nhận ý kiến để tránh tình trạng làm nổ tung do sự mất kiểm soát bất ngờ từ các số liệu đáng báo động.
Người “nuôi dưỡng”
Bạn là một người luôn tìm kiếm các tài liệu hữu ích cho các thành viên. Đồng thời, bạn cũng là người đầu tiên nhận phản hồi và chia sẻ các cập nhật. Là một freelancer it, bạn cũng thường xuyên hợp tác và giúp đỡ tra cứu tài liệu cùng các cộng sự. Chính việc quá “chăm sóc” cho nhu cầu đồng đội mà đôi khi, bạn lọt thõm trong chính nhiệm vụ của cá nhân mình.
Bạn là kiểu người hữu ích và quá nhiệt tình. Tuy vây, hãy chú ý đến bất kỳ nguyên tắc giao tiếp nào mà nhóm của bạn có thể chia sẻ một cách hiệu quả nhất. Cách tốt nhất chính là loại bỏ các đồng nghiệp không phản hồi các đề xuất ra khỏi dự án của bạn.
Thực tập sinh/hướng đạo sinh
Nếu thuộc phong cách này, bạn là kiểu người ham học hỏi. Bạn sẵn sàng giúp đỡ các đồng nghiệp khi họ khó khăn. Quan trọng, bạn thật sự yêu thích làm việc trong một nhóm. Đối với bạn, việc nhận được những phản hồi, đánh giá của người khác về bản thân mình là một điều rất tuyệt vời.
Bạn có thể kiểm tra đặc điểm tính cách của bản thân để lựa chọn công việc phù hợp thông qua công cụ trắc nghiệm tính cách tại TopDev
Nếu bạn là người thuộc kiểu phong cách cộng tác này, hãy thật sự cởi mở với những ý tưởng nghe có vẻ như chúng hoàn toàn bất hòa với chính bạn. Và đừng quá ôm đồm nhiều thứ nếu giới hạn khả năng không cho phép.
Phong cách cộng tác không áp định bất cứ ai. Chính bạn thể hiện phong cách bản thân. Cá tính bạn ra sao, xu hướng hợp tác của bạn thế nào? Tất cả đều tạo nên giá trị con người trong bạn. Để hòa nhập với một môi trường làm việc hiện đại, bạn nên cân bằng tận dụng tốt; biết phát huy những phong cách cá nhân một cách phù hợp để đạt hiệu quả tốt trong công việc. TopDev hi vọng bạn sẽ vận dụng tốt phong cách hợp tác của bản thân và có những người cộng sự tuyệt vời.
Functors là gì? Đôi khi, logic chính xác sẽ là bất khả thi bởi sự phức tạp của data trong thế giới lập trình. Do đó, data trừu tượng (data abstraction) là một tool rất hữu ích giúp ta tạo một đại diện đơn giản cho data.
Để có thể đạt được điều này, chúng ta tạo ra ‘Containers’, những container này sẽ chỉ chứa data và không làm gì khác. Ta cũng không cung cấp cho chúng những properties hoặc methods như trong lập trình hướng đối tượng OOP.
Khi cho một giá trị vào container thì nó sẽ giúp giữ giá trị đó được an toàn, trong khi được pass qua functional logic. Và ta chỉ lấy nó khi rất cần thiết. Như vậy, container có 2 task chính:
Chứa giá trị bên trong chính nó
Trả giá trị lại khi chúng ta cần
Và nó cũng không làm biến đổi giá trị.
Thật ra, những container này cũng không có gì mới, chúng ta đã sử dụng chúng kể từ khi bắt đầu JavaScripting.
Khi làm về functional programming, những containers này cực kì quyền năng, bởi chúng góp phần vào nền tảng cho cấu trúc của functional, và giúp chúng ta với những kĩ thuật như Pure Functional Error Handling và Asynchronous Actions (cùng nhiều cái khác nữa).
Trước khi đi sâu vào những container này thì mình sẽ nói về một loại container đặc biệt là Functors.
Functors là gì? Functors chính là container có thể được dùng với ‘map’ function.
Trước khi chúng ta tạo ra container cho riêng mình, hãy nhìn lại những loại container mà ta thường dùng trước đây:
Các loại container thường dùng
Arrays
Array
Arrays là loại container phổ biến nhất mà chúng ta thường dùng trong lập trình hàng ngày, thay vì chỉ chứa duy nhất một giá trị thì chúng chứa được nhiều hơn. Array là dạng đơn giản nhất của Data trừu tượng nhưng lại vô cùng mạnh mẽ.
const arr = [ 8, 10, 23, 35, 54 ];
Vậy giá trị ta có thể lấy ra giá trị trong như như sau
const b = a[1];
Giờ, nếu bạn hứa là chỉ dùng những operation này trong array, thì nó sẽ trở thành trợ thủ trung thành nhất của bạn.
Đừng bao giờ modify array như thế này:
arr.push(45)
or
arr[1] = 45
Nhưng bạn có thể dùng nó để tạo ra các array mới
const arr2 = [ ...arr, 38, 52 ]
or
const even = filter(x => x%2 === 0, arr)
Chúng ta không thay đổi bất cứ giá trị nào trong array, mà chỉ đơn giản là tạo ra array hoặc lấy giá trị ra từ nó.
Một Functor là một container mà có thể được map lên bởi một Unary function.
Nói cách khác, container có thể sử dụng với những function đặc biệt (fmap hoặc map) và nó cũng áp dụng lên mọi unary function cho đến các nội dung trong container này.
Xe tải này là functor
Với array, function đặc biệt được gọi đơn giản là map function.
Map Function
Tất nhiên không phải map này nha
Map function lấy một array và áp dụng một vài function cụ thể lên toàn bộ yếu tố của nó từng cái một và trả về một array khác.
[1,2,3,4].map(multiplyBy2)
//=> [2,4,6,8]
or
map(multiplyBy2, [1,2,3,4])
//=> [2,4,6,8]
where multiplyBy2 = x => x * 2 and map = (fn, arr) => arr.map(fn)
Từ đó, chúng ta sẽ luôn có một array mới từ map, ta cũng có thể map nó để tạo ra một chain của array.
[1,2,3].map(x => x * 3).map(x => x * 2).map(x => x / 6)
Map function không chỉ đơn thuần là một iterator function, nên nhớ rằng, với giá trị trong một container ta không thể cứ trực tiếp áp dụng một function lên nó và chờ đợi giá trị thay đổi. Ví dụ:
const a = [1, 2, 3]
String(a) = ‘[1 ,2, 3]’ and not [‘1’, ‘2’, ‘3’]
Một map function sẽ cho function truy cập vào nội dung của content
map(String, [1, 2, 3]) = [‘1’, ‘2’, ‘3’]
Ngoài ra, map function không bao giờ thay đổi container, thay vào đó nó chỉ hành động dựa trên nội dung của container..
Một map sẽ không thay đổi loại của container nhưng nó sẽ thay đổi loại content bên trong.
Type của content có thể thay đổi, và chúng ta có thể xem từ type definition của map function.
map :: a -> b -> [a] -> [b]
or
fmap :: a -> b -> F a -> F b
Với a và b có thể cùng hoặc khác loại.
Nếu bạn để ý kỹ thì map function đang lấy một function từ a -> b trả lại một function từ Fa -> Fb
Tại đây, a -> b có nghĩa là bất cứ unary function nào lấy a và trả lại b như
multiplyBy2(3) = 6 // is a -> b as 3 -> 6
và Fa -> Fb ám chỉ bất kì unary function nào lấy một Container với a bên trong và trả lại một Container với b bên trong.
multiplyArrBy2([1]) = [2] // is Fa -> Fb as [1] -> [2], F is []
Giờ map function đã thay đổi từ multiplyBy2 to multiplyArrBy2
const multiplyBy2 = no => no * 2
// We need to partially apply our map function to explain this
const map = mappingFn => arr => arr.map(mappingFn)
// Now we create our new Function now that can act upon arrays
const multiplyArrBy2 = map(multiplyBy2)
Kể từ giờ, function multiplyBy2, vốn được dùng cho integer, sẽ hành động với array của integer. Nói cách khác, map function đã promote hoặc nâng function lên để nó có thể hành động trên containers hoặc arrays trong trường hợp này.
Ta thường áp dụng một phần map function khi có thể để tạo ra các function mới hoặc dùng nó với compose function, và khi có trường hợp cực kỳ khẩn cấp của Data thì ta sẽ dùng map function bình thường.
Vậy sao lại áp dụng một phần map function?
Trước khi đi xa hơn, hẳn bạn cũng đã hiểu là ta dùng container để chứa giá trị. Ta cũng biết về Functor, vốn là những container đặc biệt mà ta có thể dùng map operation lên nó. Mặt khác, ta cũng biết cách thức map function được dùng trên Arrays, ngoài bạn cũng đã biết cách tạo ra một Container và Functor từ những ví dụ trên.
Bây giờ, Tôi xin giới thiệu container tiếp theo vốn cũng là một functor. Container đã đi cùng chúng ta ngay từ khi cuộc phiêu lưu vừa mới băt đầu.
Functions
Thế nào mà Functions lại là container?
Container chứa data, nhưng function rõ ràng là chứa logic, thế thì làm sao function có thể là container?
Đó là bởi function, khi được called sẽ trả lại một giá trị. Thế nên ta có thể hiểu là nó chứa giá trị nhưng chỉ là giá trị đó được dynamically computed.
aFunction(45) // => 90
So aFunction gives the value 90, when it is passed 45
Hãy nghĩ chúng là những arrays chứa vô hạn các value và khi bạn muốn một giá trị nào đó thì phải call function như sao:
Funtion là array với value vô hạn
Vậy Function cũng chính là container như Array?
Đúng vậy! Như array đưa giá trị khi index được pass, function đưa kết quả khi một argument được pass
const a = [ 8, 10, 23, 35, 54 ]
const f = z => z * 2
a[1] = 10
f(2) = 4
Chỉ có điều là Array yếu hơn khi nó chỉ cho kết quả khi các số nguyên là index. Còn function thì có thể lấy bất cứ type nào của arguments bởi không hề có một giới hạn nào. Thậm chí nó còn lấy những function khác làm arguments luôn.
Vậy nếu chúng là Functors thì hẳn cũng có map luôn đúng không?
Cũng như map function lấy array, áp dụng function vào content và trả lại array. Tương tự, fnMap lấy một function, áp dụng một function vào kết quả của nó và return lại function, theo cách mà nó kết hợp 2 function sao cho kết quả của một function là argument của function thứ hai.
Functions cũng là arrays, một dạng data trừu tượng. Chỉ có function tính toán data theo yêu cầu của ta.
Nói cách khác, Array giống như function nhưng chỉ đưa giá trị ngay lập tức khi ta dùng ‘[]’ lên chúng.
Chỉ cần nhớ một điều rằng giá trị chỉ có ý nghĩa khi nó nằm trong một container. Do đó trong lập trình, đừng bao giờ sử dụng Data một cách thô sơ, hãy luôn cho nó vào trong container.
Vậy đấy! Tôi hi vọng bạn đã học được thêm nhiều điều từ bài viết này!
Bài viết được sự cho phép của tác giả Edward Thiên Hoàng
Trong kiến trúc cloud (hay microservices), các ứng dụng được chia thành những khối độc lập nhỏ hơn để có thể dễ dàng develop, deploy và maintain. Hãy thử tưởng tượng bạn có một kiến trúc cloud có nhiều service và nhiều request mỗi giây, bạn phải đảm bảo rằng không có bất cứ một request nào bị mất và web service của bạn luôn luôn sẵn sàng tiếp nhận request mới thay vì locked bởi đang xử lí request trước đó cũng như phải đảm bảo rằng các service giao tiếp với nhau một cách trơn tru và hiệu quả.
Vậy bạn làm thế nào? Câu trả lời đó chính là Message Broker!
MESSAGE BROKER LÀ GÌ?
Message broker (hay còn gọi là integration broker hoặc interface engine) là một module trung gian trung chuyển message từ người gửi đến người nhận. Nó là một mô hình kiến trúc (architentural pattern) để kiểm tra, trung chuyển và điều hướng message; làm trung gian giữa các ứng dụng với nhau, tối giản hóa giao tiếp giữa các ứng dụng đó và để tăng hiệu quả tối đa cho việc tách ra các khối nhỏ hơn. Nhiệm vụ chính của một Message broker là tiếp nhận những message từ các ứng dụng và thực hiện một thao tác nào đó.
Hiện tại có rất nhiều các message broker software có thể kể đến như: Amazon Web Services (AWS) Simple Queue Service (SQS), Apache Kafka, Apache ActiveMQ. Nhưng phổ biến nhất trong số những cái tên kể trên đó là RabbitMQ!
PHÂN LOẠI GIỮA CÁC HỆ THỐNG MESSAGE QUEUE
Nếu bạn là một backend-developer chắc hẳn bạn không còn xa lạ gì với những hệ thống message-queue. Hầu như project nào của mình cũng có sự xuất hiện của message-queue và việc khó khăn nhất là lựa chọn nên dùng cái nào và không nên dùng cái nào.
Thử tưởng tượng một ngày sếp của bạn muốn tích hợp một hệ thống message queue hoặc bạn cảm thấy nên sử dụng một hệ thống message queue để giải quyết bài toán mà team đang gặp phải. Bạn bắt đầu tìm kiếm và nhận ra rằng có quá nhiều hệ thống message queue tồn tại. Mình có thể liệt kê một số loạt mà mình biết dưới đây :
RabitMQ
ActiveMQ
Kafka
SQS
ZeroMQ
MSMQ
IronMQ
Kinesis
RocketMQ
Redis Pub/sub
Trong quá khứ mình đã có không ít lần lựa trọn sai và mọi sai lầm đều phải trả giá không ít thì nhiều.
Sau những sai lầm đó thì mình nhận ra một điều, đó là mặc dù cùng là message queue nhưng lại được chia làm 2 loại có mục đich sử dụng và những tính năng liên quan hoàn toàn khác nhau.
Mình tạm chia thành 2 loại như sau:
Message Base
Data Pipeline
RabitMQ
Kafka
ActiveMQ
Kinesis
SQS
RocketMQ
ZeroMQ
MSMQ
IronMQ
Redis Pub/sub
SO SÁNH CÁCH HOẠT ĐỘNG CỦA 2 LOẠI:
Dựa vào bảng trên, ta có thể thấy được sự khác nhau cơ bản giữa 2 loại, cũng như cách sử dụng trong tưng bài toán cụ thể.
Đối với loại “message base”: là những loại message queue truyền thống, thích hợp làm hệ thống trao đổi message giữa các service. Việc đảm bảo mỗi consumer đều nhận được message và duy nhất một lần là quan trọng nhất.
Đối với loại “data-pipeline”, có cách lưu trữ message cũng như truyền tải message đến consumer hoàn toán khác với hệ thống message queue truyền thống. Việc đảm bảo mỗi consumer đều phải nhận được message và duy nhất một lần không phải là ưu tiên số một, mà thay vào đó là khả năng lưu trũ message vả tốc độ truyền tải message. Khi có message mới, consumer sẽ lựa chọn số lượng message mà mình muốn lấy, chính vì thế mà cùng một message consumer có thể nhận đi nhận lại nhiều lần. Những hệ thống sử dụng message queue loại này thường là hệ thống Event Sourcing, hoặc hệ thống đồng bộ dữ liệu từ những database khác nhau như Debezium.
Khi các bạn lựa chọn message queue cho hệ thống của mình, các bạn nên xác định rõ mục địch của hệ thống messague queue để xem mình cần loại trong hai loại trên. Việc xác định được loại message queue nào mình cần sẽ giúp các bạn giảm bớt thời gian tìm hiểu cũng như tìm được chính sác cái mà mình cần.
Đôi khi chúng ta cũng thấy một số hệ thống sẽ sử dụng nhiều loại message queue, thường sẽ là 1 của “message base” và 1 của “data pipeline” để tận dụng tối đa ưu điểm của từng loại vào giải quyết bài toán cụ thể.
MỘT SỐ MESSAGE BROKER PHỔ BIẾN
RABBITMQ
RabbitMQ là một message broker ( message-oriented middleware) sử dụng giao thức AMQP(Advanced Message Queue Protocol — Giao thức giao nhận tin nhắn sử dụng hàng đợi). Đây là chương trình đóng vai trò trung gian lưu trữ cũng như điều phối các yêu cầu (message) giữa người nhận(consumer) và người gửi(producer).
KAFKA
Kafka là nền tảng streaming phân tán, có thể mở rộng và là sản phẩm mã nguồn mở. Dự án Kafka ban đầu được phát triển bởi Linkedin sau đó trở thành dự án Apache mã nguồn mở vào năm 2011. Kafka được viết bằng ngôn ngữ Scala và Java. Nó được viết ra nhằm mục đích cung cấp một nền tảng mà có độ trễ thấp và thông lượng cao cho việc xử lý các nguồn cấp dữ liệu theo thời gian thực.
Redis hỗ trợ Transaction, hỗ trợ Pub/Sub vì vậy nó cũng được sử dụng làm hệ thống Message Broker, kinh điển là RabbitMQ sử dụng Redis là core của hệ thống.
Adobe Flash Player (hay còn gọi tắt là Flash) là một chương trình điện toán được cung cấp bởi Adobe System, công ty này cũng rất có tiếng nhờ làm ra phần mềm Photoshop và hàng loạt các phần mềm nổi tiếng khác nữa.
Quay trở lại với Flash thì nó dùng kỹ thuật đồ họa Vector và đồ họa điểm với ngôn ngữ ActionScript để truyền tải các luồng âm thanh và hình ảnh trên trang web.
Khi sử dụng Flash các tập tin đồ họa, ảnh động có kích thước khá nhỏ nên nó rất phù hợp với thời kỳ Internet tốc độ chậm mà lại có nhiều người sử dụng. Nhờ vậy mà Flash đã phát triển vượt bậc trong khoảng thời gian từ năm 2000 đến năm 2010.
Hơi khó hiểu khi tên Flash được dùng để chỉ chương trình tạo ra các tập tin Flash (*.swf) và cũng được dùng để chỉ ứng dụng có nhiệm vụ thi hành hay hiển thị các tập tin Flash đó.
Tuy Flash có nhiều chức năng như vậy nhưng cuộc chơi nào cũng đến lúc tàn, Adobe Flash Player giờ đã hết đất sống. Và…
Sau ngày 31 tháng 12 năm 2020 thì Adobe sẽ không còn hỗ trợ Flash Player nữa, chính vì thế Adobe cũng sẽ chặn nội dung Flash chạy trong Flash Player kể từ ngày 12 tháng 1 năm 2021.
=> Vậy nên Adobe khuyên tất cả người dùng ngay lập tức gỡ cài đặt Flash Player để giúp bảo vệ hệ thống. Tránh bị hacker lợi dụng khai thác.
Để tìm hiểu kỹ hơn về Adobe Flash Player thì bạn có thể đọc chi tiết hơn trong bài viết này nhé !
#1. Lý do Adobe khai tử Flash?
Về lý do khai tử Flash thì có khá nhiều lý do, nhưng chủ yếu là do bảo mật kém nên các trình duyệt web phổ biến hiện tại đều không còn hỗ trợ Flash nữa, cộng với sự phát triển quá tốt của HTML5, WebGL và WebAssembly đã đủ để thay thế cho Flash với nhiều cơ chế bảo mật tốt hơn.
Mặt khác, tốc độ Internet ngày càng nhanh nên lợi thế tiêu tốn ít băng thông của Flash dần dần không còn quá nhiều ý nghĩa nữa.
Những điểm mạnh của Flash đều được thay thế bởi những công nghệ mới như HTML5 dùng để thiết kế website, thẻ <video> trong HTML5 cùng với tốc độ Internet nhanh hơn đã giúp việc phát video có chất lượng cao hơn.
Thẻ <canvas> trong HTML5 giúp trình duyệt web vẽ và tạo hiệu ứng hoạt hình cho đồ họa bằng JavaScript.
WebGL giúp trình duyệt web hiển thị đồ họa 2D và 3D. ActionScript thì có JavaScript thay thế. Hầu như chẳng còn lý do nào để Flash nên tiếp tục tồn tại cả.
Việc khai tử Flash sẽ ảnh hưởng tới những trang web cũ đã lâu không cập nhật, vì Adobe đã ra thông báo từ năm 2017 để nhiều trang web có thời gian chuyển đổi nội dung từ Flash sang các tiêu chuẩn mới.
Còn lại thì hầu như những website lớn hiện nay đều đã loại bỏ Flash khỏi mã nguồn của trang web và thay vào đó là HTML5. Điển hình như Youtube đã thay thế Flash bằng HTML5 từ năm 2015.
Thật ra thì tương lai của Flash đã được Apple dự đoán trước, khi vào năm 2007, Apple ra mắt iPhone nhưng lại không hỗ trợ Flash trên nền tảng này, mặc dù vào thời điểm đấy Flash vẫn còn rất phổ biến.
Sau vài đời iPhone tiếp theo, vì sự phổ biến của iPhone và nhiều nhà phát triển web muốn website của họ có thể hoạt động tốt trên mọi nền tảng nên dẫn đến Flash đã có dấu hiệu suy giảm.
Vào năm 2012, Flash được coi là một rủi ro bảo mật khiến Google phải cô lập Flash với Google Chrome bằng Sandbox. Cách này khá hiệu quả khi đặt nội dung flash trong một không gian ảo của riêng mình và cô lập nó với phần còn lại của hệ thống.
Nhưng vì phải tạo ra sandbox nên đã ảnh hưởng đến hiệu năng khi sử dụng Chrome, điều này khiến cho nhiều người khó chịu và về lâu dài thì trải nghiệm người dùng Chrome sẽ bị ảnh hưởng.
Vậy nên tốt nhất vẫn là để các trang web loại bỏ Flash thì mọi thứ sẽ ổn thỏa hơn.
#2. Làm thế nào để gỡ bỏ hoàn toàn Adobe Flash Player?
Microsoft đã lên tiếng sẽ có một bản cập nhật để loại bỏ hoàn toàn Adobe Flash Player ra khỏi hệ điều hành Windows 10.
Trên Windows 10 thì Flash được Microsoft tích hợp sẵn vào hệ thống, chính vì thế bạn sẽ không thể tìm thấy phần gỡ cài đặt Flash trong phần Uninstall của Windows được. Mà nó nằm tại đường dẫn này:
C:\Windows\System32\Macromed\Flash
Đương nhiên là bạn không nên gỡ Flash bằng cách truy cập vào đường dẫn trên và xóa các file trong đó đi. Điều này có thể gây ra lỗi hệ thống. Vậy nếu bạn muốn thực hiện gỡ bỏ ngay bây giờ thì phải làm thế nào?
Cách 1: Sử dụng Adobe Flash Uninstaller
Phương pháp này là do Adobe cung cấp (hàng chính chủ). Bạn chỉ cần truy cập vào đây để tải về (link dự phòng)
Vâng, sau khi bạn tải về => chạy file => và nhấn vào UNINSTALL để thực hiện gỡ bỏ Adobe Flash Player thôi.
Cách 2: Sử dụng bản vá Windows KB4577586
Đây là bản vá do Microsoft cung cấp, tác dụng duy nhất của bản vá này là loại bỏ hoàn toàn Adobe Flash khỏi hệ thống.
Hiện tại thì bản vá KB4577586 (link truy cập bản vá tại đây) vẫn chưa được hỗ trợ thông qua Windows Update. Tuy nhiên bạn có thể tải xuống và cài đặt thủ công theo hướng dẫn chi tiết trong bài viết này:
NOTE: Bạn hãy chọn bản vá tương ứng với hệ điều hành Windows mà bạn đang sử dụng nhé. Rất đơn giản thôi !
#3. Lời kết
Okay, như vậy là trong bài viết này mình đã hướng dẫn rất chi tiết với các bạn cách gỡ bỏ Adobe Flash khỏi Windows một cách sạch sẽ và an toàn rồi nhé.
Mặc dù Flash còn nhiều hạn chế, nhưng nó đã là một phần không thể thiếu trong tuổi thơ của nhiều người.
Mình biết, từng có một thời các webgame, web xem video đều yêu cầu các trình duyệt web phải có Flash thì mới chơi hoặc xem được nội dung, vậy nên có thể nói Flash là một huyền thoại.
Adobe Flash Player trước đây có thể nói là một phần mềm/ tiện ích mặc định phải có trên bất kỳ một máy tính nào. Nhưng giờ đây nó đã bị khai tử !
Kể từ bây giờ, tuy không còn Flash nữa nhưng những tính tăng mà nó đem lại đã khởi nguồn cho một thế giới Internet với đa dạng các nội dung và tràn đầy sức sống như hiện nay.
Nguyên lý Agile – QA ngày nay đã phát triển từ “Tim lỗi” đến “Ngăn ngừa lỗi”. Những kỹ sư kiểm thử cần thêm nhiều kỹ năng khác như kiểm thử tự động, TDD, BDD và kiểm thử hộp trắng (không chỉ làm duy nhất kiểm thử hộp đen). Kỹ sư kiểm thử cần hướng đến hướng-giải-pháp, cộng tác nhiều hơn với nhóm phát triển và các bên nghiệp vụ.
Agile nghĩa là “Linh động”, “khả năng thay đổi nhanh chóng”.
Kiểm thử trong Agile không có nghĩa là một kỹ thuật kiểm thử mới, mà đi theo Agile nghĩa là phát triển một khả năng thay đổi trong tư duy để triển khai/tiến hành những gì có thể kiểm thử.
Trước khi bàn luận về kiểm thử trong Agile, hãy nhìn lại và xem xét nguồn gốc và nguyên lý bên trong Agile.
Câu chuyện xưa cũ
Trước khi thế giới làm việc với Agile, Thác nước (Waterfall) là một phương pháp có ưu thế trong công nghiệp phần mềm. Ở đây, chúng ta không giải thích mô hình Thác nước, nhưng có ghi chú vài điểm đáng chú ý trong làm việc thực tế.
Những điểm này là dựa vào kinh nghiệm của cá nhân. Có thể có khác biệt đôi chút với mọi người.
Kỹ sư phát triển (dev) và QA làm việc như những nhóm riêng lẻ (Đôi khi còn là đối thủ)
Các tài liệu liên quan được cả kỹ sư phát triển và QA xem xét cùng một lúc. Kỹ sư phát triển thiết kế và viết mã trong khi QA làm các kịch bản kiểm thử cho các tài liệu đó. Kế hoạch và việc thực thi được làm tuần tự.
Việc xem xét các kịch bản kiểm thử được tiến hành bởi trưởng nhóm QA. Việc chia sẻ các kịch bản kiểm thử cho kỹ sư phát triển không phải là một việc được khuyến khích. (Lý do: kỹ sư phát triển sẽ viết mã dựa trên các kịch bản kiểm thử và nhóm QA sẽ không thể tìm thấy lỗi).
Việc kiểm thử được xem như là công việc cuối cùng trong vòng lặp phát triển phần mềm. Hầu hết mọi lúc, QA nhận phiên bản phần mềm ở giai đoạn cuối và được mong đợi sẽ hoàn thành việc kiểm thử trong một khoảng thời gian giới hạn. (Và tất nhiên, QA đã làm được việc đó).
Mục tiêu duy nhất của QA là tìm lỗi và các khuyết điểm. Đồng thời, việc đánh giá hiệu suất làm việc của QA cũng dựa vào số lượng lỗi/khuyết điểm hợp lý mà QA tìm ra.
Chu trình kiểm thử phần mềm (STLC) và vòng đời của lỗi (Bug lifecycle) được đi theo trong quá trình thực thi. Giao tiếp qua email được khuyến kích.
Kiểm thử tự động được xem như là công việc cuối cùng và tập trung chủ yếu ở phần giao diện. Bộ kiểm thử qui hồi được xem như là ứng viên tốt nhất cho kiểm thử tự động.
Những điều trên cũng có những khuyến điểm của riêng nó
Vì kỹ sư phát triển và QA làm việc độc lập nên việc giao tiếp giữa hai bên chỉ là lỗi và khuyết điểm.
Phạm vi làm việc của QA bao gồm viết và thực thi các kịch bản kiểm thử trên sản phẩm hoàn chỉnh.
Có rất ít (hoặc không có) cơ hội cho QA xem mã nguồn hay tương tác với kỹ sư phát triển hay nhóm nghiệp vụ.
Bởi vì toàn bộ sản phẩm được đưa đến QA một lúc, trách nhiệm của QA là cực kỳ to lớn trên vòng đời của sản phẩm. QA thường được xem như “người gác đền”, và bất kể trên sản phẩm có vấn đề gì, mọi chỉ trích đều chỉ vào QA.
Như một phần của kiểm thử chức năng, kiểm thử qui hồi trên toàn bộ sản phẩm cũng là một trách nhiệm của QA, nơi mà có một lượng khổng lồ kịch bản kiểm thử cần thực thi.
Ngoài những khuyết điểm ở trên, vấn đề lớn nhất chính là “Thiếu sự tập trung vào việc cung cấp một sản phẩn với chất lượng tốt với một tốc độ hợp lý”.
Mục tiêu cuối cùng của nhóm
(cả kỹ sư phát triển và kỹ sư kiểm thử) là đưa ra một sản phẩm với chất lượng tốt, đáp ứng các yêu cầu nghiệp vụ của khách hàng và dễ sử dụng. Nhưng bởi vì những khoảng thời gian giữa những giai đoạn bị tăng lên khi đưa sản phẩm ra thị trường, trọng tâm đã bị xao lãng, mục tiêu duy nhất được duy trì là hoàn thành việc viết mã và chuyên giao cho nhóm kiểm thử để tiến hành UAT (User Acceptance Testing).
Khi đó, QA chỉ tập trung vào việc thực thi các kịch bản kiểm thử (đánh dấu vào một bảng kiểm tra), đảm bảo mọi lỗi/khuyết điểm đã được chỉnh sửa, và chuyển qua kiểm thử các chức năng khác trong hệ thống. Vậy nên, trên quan điểm của QA, trọng tâm không ở vấn đề tốc dộ và chất lượng của sản phẩm, mà là hoàn thành việc thực thi các kịch bản kiểm thử (và, tất nhiên là bao gồm cả các kiểm thử tự động, nếu có).
Nguyên lý Agile
Bắt đầu từ năm 2001, khi một nhóm gồm 17 chuyên gia gặp gỡ ở Utah (Mỹ) để trượt tuyết, ăn uống, nghĩ ngơi và có một thảo luận về chất lượng; kết quả chính là Nguyên lý Agile.
Là một chuyên gia về chất lượng, chúng ta cũng nên hiểu về bản chất của các Nguyên lý Agile và định hình lại cách suy nghĩ của chúng ta cho phù hợp với mô hình mới này.
Trước khi định hình lại cách suy nghĩ của chúng ta trong việc kiểm thử phần mềm với các nguyên lý Agile, hãy cùng làm rõ một việc: trong Agile, nhóm làm việc cần đa nhiệm và mỗi một thành viên trong nhóm đều đóng góp để phát triển sản phẩm/chức năng.
Do đó, nhóm thường được gọi là “Nhóm phát triển”, bao gồm cả lập trình viên, kỹ sư kiểm thử và phân tích nghiệp vụ. Và, các thuật ngữ lập trình viên và kỹ sư kiểm thử được dùng thay cho kỹ sư phát triển và QA.
Phần mềm hoạt động quan trọng hơn các tài liệu toàn diện về sản phẩm
Mục tiêu cuối cùng của nhóm phát triển Agile là chuyển giao ứng dụng/bản nâng cấp có khả năng sử dụng trong khoảng thời gian nhanh nhất, nghĩa là, thời gian là nhân tố chính. Nói vậy, không có nghĩa chất lượng không quan trọng. Bởi vì thời gian để đưa sản phẩm ra thị trường là giới hạn, điều quan trọng chính là một chiến lược và kế hoạch thực thi kiểm thử cần tập trung nhiều hơn vào chất lượng tổng quát của ứng dụng.
Kiểm thử là một công việc không có điểm dừng, nó có thể tiếp tục và tiếp tục, kỹ sư kiểm thử cần xác định các thông số chính mà họ có thể bật đèn xanh để sản phẩm có thể đưa ra thị trường. Để làm được điều đó, điều quan trọng là kỹ sư kiểm thử cảm thấy phù hợp khi quyết định các khái niệm “định nghĩa sự sẵn sàng” (Definition of Ready) và “định nghĩa sự hoàn thành” (Definition of Done – DoD), và cũng không nên bỏ qua “Tiêu chuẩn chấp nhận cho một tình huống/chức năng” (Acceptance Criteria of the story – AC).
Các chiến lược và kịch bản kiểm thử nên xoay quanh DoD và AC. Thay vì cố gắng viết đầy đủ các kịch bản cũng như bao gồm các thông tin mà hiếm khi được sử dụng, hãy tập trung hơn vào sự rõ ràng và các điểm chính yếu.
Điểm quan trọng ở đây là, chỉ bao gồm những thông tin mà kịch bản kiểm thử cần và có giá trị đối với kịch bản đó.
Cộng tác với khách hàng quan trọng hơn đàm phán hợp đồng
Nên có những cuộc tiếp xúc trực tiếp với khách hàng về cách tiếp cận kiểm thử và cố gắng minh bạch trong việc chia sẽ các kịch bản kiểm thử, dữ liệu kiểm thử và kết quả.
Cũng nên có những buổi họp mặt để lấy phản hồi từ khách hàng và chia sẽ kết quả kiểm thử. Hỏi khách hàng nếu họ đánh giá tốt các kết quả kiểm thử hay họ muốn có thêm những kịch bản đặc biệt. Đừng tự giới hạn bản thân trong việc đặt câu hỏi và tìm kiếm sự xác nhận từ khách hàng/nhóm nghiệp vụ để hiểu hơn về chức năng cũng như nghiệp vụ.
Càng hiểu sâu về chức năng, kỹ sư kiểm thử càng rõ ràng hơn trong việc kiểm thử.
Phản hồi với sự thay đổi quan trọng hơn bám theo kế hoạch
Thứ bất biến duy nhất chính là sự thay đổi.
Chúng ta không thể kiểm soát sự thay đổi và chúng ta hiểu và chấp nhận sự thật là, luôn luôn có sự thay đổi trong chức năng cũng như các yêu cầu; chúng ta phải thích ứng và thực hiện nó.
Tốc độ thay đổi yêu cầu được nhấn mạnh trong Agile, giống với thời trang, như một kỹ sư kiểm thử, chúng ta cần giữ cho kế hoạch kiểm thử và các kịch bản linh động đủ để thích ứng với sự thay đổi.
Theo truyền thống, chúng ta tạo kế hoạch kiểm thử và mọi thứ đi theo vòng đời của dự án. Ngược lại, trong Agile, kế hoạch cần linh động với từng yêu cầu. Một lần nữa, hãy tập trung vào DoD và AC.
Không cần thiết phải tạo ra kế hoạch kiểm thử cho từng tình huống/chức năng; thay vào đó, có thể tạo các kế hoạch kiểm thử ở mức độ Epic. Khi một Epic được thiết lập và tiến hành, có thể đồng thời tiến hành tạo ra kế hoạch kiểm thử cùng lúc. Quan trọng là, kỹ sư kiểm thử cần bao phủ chất lượng của toàn bộ Epic với kế hoạch kiểm thử đó.
Có thể sử dụng PI (Product Increment) để xác định các kịch bản kiểm thử tổng quát cho từng tình huống dựa vào DoD và AC.
Truyền thông giao tiếp và sự tương hỗ quan trọng hơn quy trình và công cụ
Kỹ sư kiểm thử thường có xu hướng nghiên về quá trình (process-oriented), nhưng chúng ta cần nhớ rằng, thay vì đi theo chu trình, thời gian đáp ứng không nên bị ảnh hưởng.
Với trường hợp nhóm làm việc cùng địa điểm, bất kỳ vấn đề nào cũng có thể giải quyển thông qua đối thoại trực tiếp. Có lẽ việc họp mặt hằng ngày (daily stand-ups) cung cấp một giải pháp tốt để giải quyết các vấn đề. Việc ghi nhận/tài liệu hóa lỗi/khuyết điểm là quan trong, nhưng nó chỉ nên được làm cho mục đích ghi dấu (tracking) mà thôi.
Tester nên làm việc chung với Dev và hợp tác để giải quyết các khuyết điểm. Nếu cần, khách hàng cũng nên tham gia chung. Kỹ sư kiểm thử nên chủ động tham gia vào quá trình TDD và cũng nên cộng tác với lập trình viên để chia sẽ các kịch bản và cố gắng xác định lỗi ở ngay mức độ đơn vị.
Kết luận
Kiểm thử trong Agile không phải là kỹ thuật mới. Nó là sự thay đổi trong suy nghĩ, và sự thay đổi diển ra một cách liên tục. Nó yêu cầu các kiến thức, kỹ năng và sự hướng dẫn đúng đắn.
Quá nhiều người dùng truy cập sẽ dẫn đến lượng request khổng lồ, server trở nên quá tải, ảnh hưởng không hề nhỏ đến công suất hoạt động của website, ứng dụng nói riêng và kết quả kinh doanh nói chung. Trong các tình huống như vậy, áp dụng load balancer để cân bằng tải cho server sẽ là giải pháp tối ưu.
Một router hay hoặc load balancer hỗ trợ sticky session có thể gán một máy chủ đơn lẻ cho một người dùng cụ thể, dựa trên HTTP session hoặc địa chỉ IP của họ. Máy chủ được chỉ định sẽ được router ghi nhớ trong một khoảng thời gian nhất định, đảm bảo rằng tất cả các yêu cầu trong tương lai cho cùng một session sẽ được gửi đến cùng một máy chủ.
Sticky session là một trong các tính năng cơ bản của nhiều giải pháp load balancer nhằm cân bằng tải cho các website. Tính năng này route các yêu cầu cho một session cụ thể đến cùng một máy tính vật lý, và máy tính này phục vụ yêu cầu đầu tiên cho session đó. Tính năng này chủ yếu được sử dụng để đảm bảo một in-proc session nào đó sẽ không bị mất bởi các yêu cầu cho session được route đến các máy chủ khác nhau. Vì yêu cầu từ 1 người dùng luôn được route đến cùng một máy đã phản hồi yêu cầu lần đầu cho session đó, các sticky session có thể gây ra phân phối tải không đồng đều trên các máy chủ.
Ngoài ra, load balancer cũng có thể duy trì các sticky session thay vì phải nhớ địa chỉ ip của máy khách và máy chủ backend mà máy khách đã gửi đến lúc đầu.
Lợi ích
– Không quá phức tạp để triển khai đối với quản trị viên mạng có kinh nghiệm.
– Giảm nhu cầu triển khai chuyển đổi dự phòng, vì yêu cầu người dùng sẽ chỉ được gửi tới các máy chủ khác nếu một máy chủ offline.
– Load balancer/router thường chịu trách nhiệm phát hiện các máy chủ offline, cung cấp yêu cầu chuyển đổi dự phòng nhanh hơn so với round robin của load balancing dựa trên DNS.
2. Tính năng Health check backend
Server Load Balancer sẽ kiểm tra tính khả dụng dịch vụ của các backend server bằng cách thực hiện health check. Chức năng health check giúp cải thiện tính sẵn sàng cho toàn bộ dịch vụ và tránh tác động xấu từ các lỗi trên server backend.
Sau khi kích hoạt health check, Server Load Balancer sẽ ngừng phân phối các request đến các phiên bản được xác minh là không đạt yêu cầu hoặc lỗi và chỉ khởi động lại việc chuyển tiếp request đến phiên bản đó khi nó được khai báo là đã đạt yêu cầu.
Tính năng này giúp kiểm tra trạng thái máy chủ ở backend để đẩy request vào các server group không bị lỗi.
Quy trình hoạt động của health check
Server Load Balancer thường được triển khai theo cụm/cluster. Chuyển tiếp dữ liệu và health check sẽ được xử lý đồng thời bởi các node servers trong LVS cluster và Tengine cluster.
Các node servers trong cluster độc lập sẽ thực hiện health check song song, theo cấu hình của health check. Nếu một node server phát hiện ra một khu vực nào đó bị lỗi, node server sẽ ngừng phân phối request tới khu vực đó. Thao tác này sẽ được đồng bộ hóa trên tất cả các node server như trong sơ đồ dưới đây.
3. Tính năng theo dõi giám sát hoạt động (Operational Monitoring)
Một số các thông số trong Load balancer cần theo dõi, giám sát:
Healthy host count: Số lượng các trường hợp không bị lỗi trong load balancer. Một trường hợp được coi là “healthy” – đạt tiêu chuẩn nếu nó đáp ứng ngưỡng tiêu chuẩn được cấu hình cho health check.
Unhealthy host count: Số lượng các trường hợp lỗi trong load balancer. Một trường hợp được coi là lỗi nếu nó vượt quá ngưỡng tiêu chuẩn lỗi được cấu hình cho health check. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.
Request Count: Số lượng request trọn vẹn được nhận và chuyển đến các phiên bản đăng ký. (The number of completed requests that were received and routed to the registered instances.)
Latency: Thời gian tính từ sau khi request rời khỏi load balancer cho tới lúc nhận được phản hồi (được tính bằng giây và không được lớn hơn 0 trừ khi máy chủ đang được bảo trì).
Lỗi kết nối Backend: Số lượng kết nối không thành công giữa load balancer và phiên bản đăng ký. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.
Độ dài Surge Queue Length: Tổng số request đang chờ gửi đến phiên bản đăng ký. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.
Spillover Count: Tổng số request bị từ chối khi quêu đã full. Số này không được lớn hơn 0 trừ khi máy chủ đang trong thời gian bảo trì.
Nhiều nghiên cứu cho thấy, những người thành công hầu như đều sở hữu cho mình những thói quen tích cực. Chúng cũng có ý nghĩa lớn, chi phối đến những quyết định quan trọng của họ. Song, quá trình ấy cần họ chọn lọc và nỗ lực rèn luyện bởi có rất nhiều thói quen tiêu cực bủa vây. Cùng TopDev tìm hiểu về 4 thói quan bạn cần thay đổi nếu muốn trở thành người thành công!
Dấu hiệu sinh hoạt chưa khoa học
Những dấu hiệu cụ thể mà một người khó thành công đó là: Ngủ quá nhiều, nghĩ quá nhiều về mọi thứ; hoặc thậm chí là ăn quá nhiều.
Những thói quen tiêu cực sẽ tác động nếu bản thân bạn không nhận ra chúng!
Điều bạn cần làm để thay đổi là việc tự rèn luyện và chủ động cải thiện thay đổi các thói quen. Hãy tập ra khỏi giường đúng giờ. Đừng “nướng” qáu lâu để rồi ảnh hưởng đến chất lượng và hiệu quả của công việc.
Quan tâm nhiều đến khối óc của bạn. Đừng suy nghĩ quá nhiều nếu bạn cảm thấy có dấu hiệu của sự căng thẳng. Việc làm cho tâm trí bạn thư giãn là có ý nghĩa rất quan trọng đến sưc khỏe tinh thần của bạn.
Ngưng hóng hớt “chuyện đời – chuyện người”
Đây là biểu hiện của một người sẽ khó thành công. Khi hóng hớt tức là bạn đang soi mói, “tìm tòi” những khía cạnh tiêu cực của người khác.
Điều này vô tình tạo ra một sự lãng phí năng lượng tinh thần khổng lồ. Đồng thời, bạn khó có thể tập trung vào việc phát triển bản thân. Từ đó dẫn đến việc bạn dậm chân tại chỗ.
Những mục tiêu phi thực tế
Không một người nào thành công nào mà không xác lập mục tiêu cho mình cả. Tuy nhiên, nếu bạn có mục tiêu thì nó phải đảm bảo tính khả thi.
Mục tiêu, kế hoạch cần dược chuẩn hóa xây dựng một cách khoa học. Cụ thể, nó được thiết lập dựa trên các hệ giá trị như năng lực, tính cách, môi trường,… Nếu không bạn sẽ dễ dàng rơi vào trạng thái căng thẳng. Và tất nhiên, bạn khó có thể thực hiện bất cứ điều gì cả.
Áp lực từ việc trở thành người đa nhiệm
Nhiều người thành công họ không chỉ đơn thuần ở việc chỉ làm một công việc, một nhiệm vụ nào đó. Họ thực hiện rất nhiều task, các dự án thậm chí quản lý rất nhiều dự án lớn nhỏ khác nhau.
Tuy nhiên, nếu chưa có đủ sự trải nghiệm về kỹ năng chuyên môn cùng việc áp dụng thực tế, bạn khó có thể thành công.
Một freelancer IT không thể tự tin nhận nhiều job nếu chuyên môn của họ không thật sự giỏi. Trở thành người đa nhiệm thật sự không hề dễ dàng. Đó là một quá trình dài và vì thế, đừng cố sức nếu bạn chưa đủ sức thực hiện.
Khai bút đầu xuân, cũng là đánh dấu sự trở lại sau một thời gian kha khá dài không có bài viết thường xuyên cập nhật. Với mục tiêu cho năm mới đó là cống hiến nhiều hơn, mặc dù dạo gần đây và trong tương lai gần thì mình không có nhiều thời gian rảnh buổi tối để làm anh hùng bàn phím như này nữa.
Bài viết đầu tiên đậm chất kỹ thuật, khô khan nhưng lại chứa hàm lượng kiến thức vừa đủ để có thể áp dụng vào thực tế. :))) Hi vọng rằng bài viết sẽ có chút hữu ích cho các bạn nào cần thông tin – cũng là làm phong phú thêm kết quả tìm kiếm hiển thị trên Google search! – Cũng là một cách cống hiến đúng không nào!
Đầu tiên tìm hiểu một chút về SSL Certifycate, mình nói sơ qua lý thuyết thôi, vì thực tế là cả tài liệu tiếng Việt và tiếng Anh đều cung cấp rất đầy đủ và chi tiết về cái này rồi, như nó là gì, phân loại ra sao, mục đích sử dụng như thế nào, những lợi ích mà nó đem lại cho người dùng là gì… và cùng rất nhiều thông tin khác nữa, nói ra thì dài lắm, nên các bạn cần thì tự tìm hiểu thêm, ở đây là mức vừa đủ để khỏi bỡ ngỡ thui nha!
SSL Cetificate là gì?
SSL là viết tắt của Secure Socket Layer, là một tiêu chuẩn an ninh công nghệ toàn cầu tạo ra một liên kết được mã hóa giữa máy chủ web và trình duyệt. Liên kết này đảm bảo tất cả các dữ liệu trao đổi giữa máy chủ web và trình duyệt luôn được bảo mật và an toàn.
Chứng thư số SSL tích hợp trên ứng dụng client để người dùng khi truy cập có thể xác minh được tính xác thực, tin cậy của website, đảm bảo mọi dữ liệu, thông tin trao đổi giữa ứng dụng và người dùng được mã hóa, tránh nguy cơ bị can thiệp. Các bạn xem qua cách thức hoạt động theo sơ đồ phía dưới:
Chúng ta sẽ quan sát thấy thông tin chứng chỉ SSL như vùng khoanh ở hình ảnh phía dưới, khi click vào sẽ hiển thị popup thông tin nhỏ phía dưới:
Liên quan đến SSL Certification, trên các trình duyệt sẽ có thông báo hiển thị khác nhau như:
Chrome:
FireFox:
IE:
Trên thực tế khi viết các automation script, không phải sẽ gặp phải tình huống này quá thường xuyên, nhưng cũng là một trường hợp tương đối đặc biệt mà mình nghĩ là nếu hiểu và biết cách xử lý thì sẽ có hướng tiếp cận nhanh và phù hợp hơn.
Đối với từng loại trình duyệt thì sẽ có những điều chỉnh tương ứng với trình duyệt đó, tùy thuộc vào trình duyệt mà bạn dự định sẽ thực thi test, lý do vì sao thì chính là mấy hình ảnh phía trên kia chính là câu trả lời đó! :)))
Ở đây mình sẽ tổng hợp lại các bước để xử lý được trường hợp này, cơ bản là cũng không có đưa ra được cụ thể một link ví dụ nào để thực hành, nếu gặp trong thực tế, thì các bạn có thể thử áp dụng luôn, nếu có vướng mắc gì thì có thể liên hệ với mình để cùng tìm cách giải quyết nhé!
//FireFox:
FirefoxProfile ffProfile = new FirefoxProfile();
ffProfile.setAcceptUntrustedCertificates(true); ffProfile.setAssumeUntrustedCertificateIssuer(false);
FirefoxDriver driver = new FirefoxDriver(ffProfile)
Trên trình duyệt IE:
Điểm khác với hai trình duyệt phía trên, ta phải thực hiện một bước trước khi thực hiện tương tác với Certificate, thì sẽ phải thực hiện bước điều hướng bằng cách sử dụng Javascript executor:
Sau đó thực hiện tương tự như thực hiện phía trên với Chrome/Firefox:
DesiredCapabilities cap= new DesiredCapabilities();
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
System.setProperty("webdriver.ie.driver","IEDriverServer.exe");
WebDriver driver = new InternetExplorerDriver(capabilities);
Trên đây là các bước thực hiện giúp bạn xử lý SSL certificate với Selenium đối với các trình duyệt Chrome, FireFox và IE. Các bạn có thể thử và nếu có vấn đề gì thì để lại bình luận phía dưới hoặc liên hệ trực tiếp với mình nhé. Mình không chắc sẽ đưa ra ngay được đáp án chính xác tuy nhiên sẽ hứa cùng các bạn tìm hiểu vấn đề và giải quyết vấn đề :))))
Chúc mừng năm mới, nhiều điều mới mẻ và tốt đẹp sẽ chào đón chúng ta! <<tung hoa, tung hoa>>
Bài viết được sự cho phép của tác giả Edward Thiên Hoàng
CÁC PATTERNS VỀ SỰ NHẤT QUÁN (CONSISTENCY)
Với nhiều bản sao của cùng một dữ liệu, chúng ta phải đối mặt với các tùy chọn về cách đồng bộ hóa để client có một cái nhìn nhất quán về dữ liệu.
TÍNH NHẤT QUÁN LỎNG LẺO (WEAK CONSISTENCY)
Sau một lệnh ghi, có thể đọc được hoặc không được ngay lập tức.
Cách tiếp cận này được thấy trong các hệ thống như memcached. Tính nhất quán yếu, lỏng lẻo hoạt động tốt trong các use cases thời gian thực như VoIP, trò chuyện video và trò chơi nhiều người chơi trong thời gian thực. Ví dụ: nếu bạn đang thực hiện một cuộc gọi điện thoại và mất liên lạc trong vài giây, khi bạn lấy lại kết nối, bạn không nghe thấy những gì được nói trong khi mất kết nối.
CÁC PATTERNS VỀ TÍNH KHẢ DỤNG, SẴN SÀNG (AVAILABILITY)
Có hai patterns chính để hỗ trợ tính khả dụng cao (high availability): fail-over (chuyển đổi dự phòng) và replication (nhân bản).
FAIL-OVER
ACTIVE-PASSIVE
Với chuyển đổi dự phòng dạng active-passive, các lệnh check heartbeats được gửi giữa máy chủ active và máy chủ passive ở chế độ standby. Nếu heartbeats bị gián đoạn, máy passive sẽ chiếm địa chỉ IP của máy active và tiếp tục dịch vụ.
Thời gian ngừng hoạt động được xác định bởi liệu máy passive đã chạy ở chế độ ‘hot’ standby hay liệu nó có cần khởi động từ chế độ ‘cold’ standby hay không. Chỉ có máy chủ active xử lý request.
Chuyển đổi dự phòng dạng active-passive cũng có thể được gọi là chuyển đổi dự phòng master-slave.
ACTIVE-ACTIVE
Trong active-active, cả hai máy chủ đều xử lý request, phân tán tải giữa chúng.
Nếu các máy chủ được công khai ra internet, DNS sẽ cần biết về IP công khai của cả hai máy chủ. Nếu các máy chủ nằm trong nội bộ, logic ứng dụng sẽ cần biết về cả hai máy chủ.
Chuyển đổi dự phòng hoạt động active-active cũng có thể được gọi là chuyển đổi dự phòng master-master.
NHƯỢC ĐIỂM CỦA CHUYỂN ĐỔI DỰ PHÒNG
Chuyển đổi dự phòng thêm phần cứng và tăng độ phức tạp.
Có khả năng mất dữ liệu nếu hệ thống hoạt động bị lỗi trước khi bất kỳ dữ liệu mới được ghi nào có thể được nhân rộng (replicate) sang máy passive.
NHÂN RỘNG (REPLICATION)
MASTER-SLAVE REPLICATION
Máy chủ master phục vụ đọc và ghi, sao chép ghi vào một hoặc nhiều máy slave chỉ phục vụ đọc. Các slave cũng có thể sao chép thêm các slave theo kiểu giống như mô hình cây. Nếu master ngừng hoạt động, hệ thống có thể tiếp tục hoạt động ở chế độ chỉ đọc cho đến khi một máy slave được thăng cấp thành master hoặc có một master mới được cung cấp.
Nhược điểm:
Cần logic để thăng cấp một máy slave thành máy master.
Có khả năng mất dữ liệu nếu máy master bị lỗi trước khi bất kỳ dữ liệu mới được ghi nào có thể được sao chép sang các máy salve khác.
Việc nhân rộng yêu cầu phải thêm phần cứng và tăng thêm độ phức tạp.
MASTER-MASTER REPLICATION
Cả hai máy master phối hợp với nhau phục vụ đọc ghi. Nếu một trong hai chủ bị hỏng, hệ thống có thể tiếp tục hoạt động với cả đọc và ghi.
Nhược điểm:
Sẽ cần đến một bộ cân bằng tải hoặc sẽ cần thay đổi logic ứng dụng để xác định nơi ghi.
Hầu hết các hệ thống master-master đều có tính nhất quán lỏng lẻo (vi phạm ACID) hoặc tăng độ trễ ghi do đồng bộ hóa.
Giải quyết xung đột xuất hiện nhiều hơn khi nhiều nút ghi được thêm vào và do đó sẽ làm tăng độ trễ (latency).
Và tất nhiên, việc nhân rộng yêu cầu phải thêm phần cứng và tăng thêm độ phức tạp.
CÁC TÍNH KHẢ NĂNG KHẢ DỤNG
Tính khả dụng thường được định lượng theo thời gian hoạt động (hoặc thời gian chết) theo phần trăm thời gian dịch vụ có sẵn. Tính khả dụng thường được đo bằng số lượng các số 9 – một dịch vụ có 99,99% khả dụng được mô tả là có bốn số 9.
99.9% AVAILABILITY – 3 SỐ 9
Duration
Acceptable downtime
Downtime per year
8h 45min 57s
Downtime per month
43m 49.7s
Downtime per week
10m 4.8s
Downtime per day
1m 26.4s
99.99% AVAILABILITY – FOUR 9S
Duration
Acceptable downtime
Downtime per year
52min 35.7s
Downtime per month
4m 23s
Downtime per week
1m 5s
Downtime per day
8.6s
KHẢ DỤNG SONG SONG VS THEO TRÌNH TỰ
Nếu một dịch vụ bao gồm nhiều thành phần dễ bị lỗi, tính khả dụng chung của dịch vụ phụ thuộc vào việc các thành phần đó theo trình tự hay song song.
THEO THỨ TỰ
Tính khả dụng chung giảm khi hai thành phần có sẵn < 100% theo thứ tự:
Tính khả dụng (tổng) = Tính khả dụng (Foo) * Tính khả dụng (Bar)
Nếu cả Foo và Bar đều có sẵn 99,9%, tổng số khả dụng của chúng theo thứ tự sẽ là 99,8%.
SONG SONG
Tính khả dụng chung tăng khi hai thành phần có sẵn < 100% song song:
Tính khả dụng (tổng) = 1 – (1 – khả dụng (Foo)) * (1 – khả dụng (Bar))
Nếu cả Foo và Bar đều có sẵn 99,9%, thì tổng khả dụng song song của chúng sẽ là 99.9999%.
Như các bạn đã biết, các máy tính hiện đại ngày nay có bộ xử lý trung tâm là CPU (hay còn gọi là Chip) đang dần đạt đến giới hạn vật lý có thể đạt được.
Hiện tại là tiến trình 7nm, tương lai các CPU chỉ còn 2nm thậm chị là 1nm. Khi các bóng bán dẫn đạt tới mức này, việc thu nhỏ thêm là vô cùng khó khăn.
Nhiều chuyên gia và người yêu công nghệ cho rằng, để thay cho giải pháp bóng bán dẫn, các nhà khoa học sẽ nghiên cứu tới các máy tính lượng tử (cấp độ phân tử).
#1. Máy tính lượng tử là gì?
Khác với máy tính kỹ thuật số, máy tính lượng tử hoạt động dựa trên hoạt động của cơ học lượng tử, để xử lý dữ liệu đầu vào. Như vậy, hiểu đơn giản máy tính lượng tử là máy tính hoạt động trên cơ sở của những hạt lượng tử.
Các hoạt động chủ yếu của lượng tử được áp dụng vào máy tính lượng tử là tính chồng chập và vướng víu lượng tử.
Không giống với các máy tính kỹ thuật số thông dụng ngày nay, dữ liệu được mã hóa thành số nhị phân (bit) và gán cho nó 2 giá trị TẮT và MỞ tương ứng là 0 và 1. Và nó chỉ có thể nhận được 1 trong 2 giá trị 0 hoặc 1.
Còn các máy tính lượng tử sử dụng đơn vị là “qubits” (quantum bits, bits lượng tử ) với các giá trị nằm trong khoảng từ 0 tới 1. Nó có thể nhận được cả 2 giá trị 0 và 1 cùng một lúc.
Để có thể giải thích thì nguyên lý hoạt động của máy tính lượng tử dựa trên 2 hoạt động cơ học là tính chồng chập và vướng víu lượng tử là rất khó hiểu với đại đa số chúng ta, nên mình xin phép không đề cập đến.
Chúng ta chỉ cần biết rằng máy tính lượng tử là máy tính từ những hạt cơ bản (lượng tử) và nó hoạt động nhờ trên các hoạt động của cơ học lượng tử.
#2. Khả năng tính toán gấp nhiều lần so với máy tính kỹ thuật số
Theo nghiên cứu, các máy tính lượng tử có khả năng xử lý theo cấp số nhân (theo số lượng qubits). Chỉ với việc tăng một số lượng nhỏ qubits thì ta sẽ có gấp nhiều lần năng lực xử lý của máy tính.
Tuy nhiên, đó là chỉ là trên lý thuyết, việc thêm một lượng qubits phải đảm bảo không có lỗi nào trong quá trình xảy ra rối lượng tử và chỉ vài sai lệnh nhỏ trong vấn đề tính toán là mọi việc đều công cốc.
Không giống với các máy tính thông thường, các máy tính lượng tử có hình dáng khá là đặc biệt, chúng trông giống như một chiếc đèn chùm khổng lồ và các chuyên gia cũng gọi đó là kiến trúc đèn chùm.
Hình dạng máy tính lượng tử
Cũng giống như các máy tính thông thường, máy tính lượng tử cũng có một nhân trung tâm là một siêu chip với các qubit được sắp xếp theo dạng bàn cờ vua.
Nhân chip và cụ thể là các qubits có cấu tạo là các vi tụ điện được làm từ Niobium với độ cứng ngang với Titan.
Các cực của qubit được làm để dao động, và không duy trì một trạng thái cố định nào, chính vì lý do này nên máy tính lượng tử có khả năng xử lý mạnh hơn máy tính thông thường.
Nhân chip máy tính lượng tử
Con chip này được đặt trong một trường vi sóng điện từ, hoạt động trong điều kiện lạnh, cực lạnh, thậm chí ở mức gần 0oK.
Để đạt được ngưỡng nhiệt này, cách hiệu quả và ít tốn kém nhất hiện tại là máy tính sẽ được nhấn chìm trong một bể Heli lỏng.
#4. Phần mềm của máy tính lượng tử
Nếu bạn trông chờ máy tính lượng tử cũng chạy hệ điều hành, hay các soft như máy tính thông thường thì đã làm các bạn thất vọng rồi. Thực tế thì hiện nay không có một phần mềm nào hoạt động được trên máy tính lượng tử.
Để kiểm tra khả năng xử lý của máy tính, các chuyên gia đã phải nghiên cứu ra các tác vụ công cụ riêng đặc biệt có thể nói là độc nhất vô nhị để chạy trên siêu máy tính này.
Có thể thấy rõ, tuy chúng ta đã đạt được những bước tiến lớn trong ngành này nhưng vẫn chưa thể áp dụng lên thực tiễn được.
Nếu so sánh với việc sản xuất máy bay thì chúng ta chỉ đang ở giai đoạn những chiếc máy bay đầu tiên trên thế giới, chỉ nhấc lên khỏi mặt đất chứ không thể gọi là bay đúng nghĩa.
Sẽ còn quá sớm để nói rằng máy tính lượng tử sẽ được ứng dụng vào cuộc sống, ít nhất cũng cần 40 tới 50 năm nữa chúng ta mới có được những chiếc máy lượng tử ứng dụng vào phổ thông.
Trong khoảng thời gian đó, máy tính kỹ thuật số sẽ đứng trước chướng ngại vật lý về kích thước bóng bán dẫn, chúng ta chỉ có thể chờ xem liệu tiến bộ khoa học sẽ làm gì với rào cản này.
Trên đây là bài viết cơ bản nhất về máy tính lượng tử, một ngành khoa học mới và vô cùng phức tạp. Bài viết nhằm đem lại cho các bạn những kiến thức cơ bản và dễ hiểu nhất về máy tính lượng tử nên không tránh khỏi những thiếu sót.
Câu hỏi này là đề tài tranh luận phức tạp. Kỹ sư phát triển kiểm thử mã của họ. Kết quả của quá trình kiểm thử này là gì? Phải chăng là toàn bộ những luồng làm việc của hệ thống? Thông thường, kỹ sư phát triển chỉ nhìn thấy những luồng làm việc chính và cơ bản của sản phẩm, và thường không đi sâu vào chi tiết từng luồng làm việc khác nhau. Kỹ sư kiểm thử giỏi sẽ giúp app không bị crash ở những luồng không mong muốn.
Vấn đề chính trong việc kiểm thử do kỹ sư phát triển tiến hành là việc không nắm rõ, hiểu nhầm các yêu cầu chức năng. Nếu một yêu cầu chức năng bị hiểu nhầm bởi kỹ sư phát triển, bất kế kỹ sư phát triển tiến hành kiểm thử sâu đến mức độ nào, lỗi sẽ không bao giờ được tìm thấy. Và lỗi sẽ được kỹ sư phát triển nhìn nhận, ngay từ ban đầu, như một chức năng – It’s not a bug, it’s a feature 🙂
Những kỹ sư phát triển cho rằng: mã do tôi viết và tôi tự tin nó hoạt động một cách chính xác. Không cần phải kiểm thử luồng làm việc này, không cần kiểm thử cách ứng xử kia, và tôi biết là nó/ứng dụng làm việc một cách chính xác và hợp lý. Kết quả là, kỹ sư phát triển bỏ qua khả năng xảy ra lỗi.
Kỹ sư phát triển và kỹ sư kiểm thử
Kỹ sư phát triển luôn cảm thấy mã hoạt động chính xác. Và anh ta sẽ làm kiểm thử để khẳng định mã hoạt động chính xác. Nhưng, lý do gì đển kỹ sư kiểm thử tiến hành kiểm thử ứng dụng? Để tìm ra lỗi ở một điểm nào đó và kỹ sư kiểm thử tiến hành kiểm thử để chứng minh ứng dụng không làm việc một cách chính xác. Đây chính là điểm khác biệt chính trong cách tiến hành kiểm thử của kỹ sư phát triển và kỹ sư kiểm thử.
Kỹ sư phát triển có nên làm kiểm thử với mã của họ?
Về cá nhân, tôi không có vấn đề gì nếu kỹ sư phát triển kiểm thử mã của họ. Sau tất cả, đó là sản phẩm của họ. Họ biết mã rất rõ. Họ biết các bẫy trong mã. Nơi mã có thể có lỗi, nơi nào cần chú ý nhiều hơn, đâu là luồng làm việc quan trọng của ứng dụng. Kỹ sư phát triển có thể tiến hành các kiểm thử đơn vị và có thể thiết lập những trường hợp biên – boundary cases.
Đó là tất cả những gì để kỹ sư phát triển có thể trở thành một kỹ sư kiểm thử tốt. Nhưng, hầu hết kỹ sư phát triển nhìn nhận kiểm thử là một công việc mệt mỏi, bất kể họ hiểu hệ thống tốt như thế nào họ cũng sẽ bỏ qua nhiều luồng kiểm thử khác nhau. Nếu một kỹ sư phát triển tìm thấy lỗi trong mã của họ khi đang tiến hành kiểm thử đơn vị, lỗi sẽ tương đối dễ chỉnh sửa, một phần vì mã vừa mới được viết ra; hơn là chỉnh mã để sửa lỗi do nhóm kiểm thử tìm thấy vài ngày sau đó. Nhưng, việc này cũng chỉ hiệu quả khi mà kỹ sư phát triển cảm thấy hứng thú với việc kiểm thử.
Trách nhiệm của kỹ sư kiểm thử là đảm bảo tất cả các luồng làm việc của hệ thống đều được kiểm thử. Kỹ sư kiểm thử nên chỉ ra sự quan trọng của từng vấn đề khả dĩ để kiểm tra rằng hệ thống không bị thiếu sót ở bất kỳ đâu.
Mỗi người trong nhóm đều là chuyên gia trong từng lĩnh vực của họ. Kỹ sư phát triển thường nghĩ về cách phát triển ứng dụng trong khi kỹ sư kiểm thử nghĩ về cách người dùng cuối sử dụng ứng dụng đó.
Kết luận
Vậy nên, về cơ bản, sẽ không có vấn đề gì nếu kỹ sư phát triển tiến hành những bài kiểm thử đơn vị cơ bản. Kỹ sư phát triển có thể kiểm thử vài điều kiện đặc biệt mà họ biết là nghiêm trọng và không thể bỏ qua. Nhưng vẫn còn những kỹ sư kiểm thử giỏi trong nhóm. Đừng phí thời gian của kỹ sư phát triển. Để dự án thành công, cần có đội ngũ kiểm thử độc lập để kiểm thử ứng dụng. Và, sau cùng, trách nhiệm của kỹ sư kiểm thử là làm cho sản phẩm tốt hơn cho người dùng.
Trong Dự án React cho người mới bắt đầu này, chúng ta sẽ học cách xây dựng các biểu mẫu cơ bản bằng cách sử dụng React hook.Chúng ta sẽ tìm hiểu cách quản lý state biểu mẫu, xử lý xác thực và làm việc với trình xử lý gửi.
Kiểm tra thử nào:
Bắt tay xử lý vấn đề
Nếu bạn muốn tự mình thực hiện trước, đây là các tình huống (bạn cũng có thể lấy CSS / source code bên dưới):
Người dùng có thể nhập các giá trị vào biểu mẫu React Hooks
Khi người dùng nhấp vào gửi, nếu bất kỳ trường nào trống, thì thông báo lỗi sẽ xuất hiện màu đỏ
Nếu biểu mẫu được gửi và hợp lệ, thông báo thành công sẽ xuất hiện
Chúng ta sẽ bắt đầu bằng cách thêm một đối tượng state để giữ biểu mẫu của React Hooks. Chúng ta sẽ lấy một dòng mới ở đầu App function trong App.js và thêm phần sau:
Chúng ta có ba trường trên biểu mẫu mà chúng ta cần biết state.
Bây giờ, state ban đầu sẽ là một đối tượng.Và đối tượng này sẽ có ba giá trị, một giá trị cho mỗi trường này.Vì vậy, chúng ta sẽ gọi chúng một cái gì đó tương tự như những gì chúng được gọi trong biểu mẫu.
firstName sẽ được đặt thành trống ban đầu, giống với lastName và giống với email.
Và bây giờ, bạn sẽ nhận thấy lỗi “useState is not defined”, vì vậy bạn cần nhập nó từ React tại đây.Thực hiện việc này ở đầu tệp như một phần của quá trình nhập:
import React, { useState } from "react";
Được rồi, bây giờ nó cho chúng ta biết rằng các biến này chưa được sử dụng.Điều này là tốt vì chúng ta chưa áp dụng các giá trị này cho biểu mẫu của React Hooks.Nhưng tất cả những gì chúng ta đã làm cho đến nay là chúng ta đã tạo một đối tượng state và đối tượng state này kéo firstName, lastName và email.
Bây giờ chúng ta có một số giá trị ở state, nên áp dụng chúng vào các trường input.Thêm một thuộc tính value vào mỗi trường input của bạn như sau:
Tất cả những gì chúng ta đã làm ở đây là nói, “Được rồi, đối với input này, giá trị sẽ là bất kỳ giá trị nào ở state.”Hãy lưu điều này và xem những gì đang diễn ra trong các biểu mẫu trong React Hooks, để đảm bảo mọi thứ vẫn hoạt động.
Nếu bạn chọn một input và bắt đầu gõ mạnh trên bàn phím, không có gì xuất hiện trên màn hình.Vậy điều gì đang xảy ra ở đây?
Cập nhật input states
Chà, chúng ta đã nói rằng giá trị của input này sẽ là bất kể nó ở state nào.
Ví dụ: firstName hiện được đặt thành trống vì đó là những gì chúng ta đặt nó thành, nhưng chúng ta chưa nói với input, “Được rồi. Bất cứ khi nào tôi nhập hoặc input thay đổi, tôi muốn bạn tiếp tục và cập nhật state mớicác giá trị. “
Bất cứ khi nào chúng ta làm những việc như thế này, nó sẽ cho phép React hooks kiểm soát một cách hiệu quả.Vì vậy, chúng ta phải yêu cầu React hooks cập nhật các giá trị.
Điều này có nghĩa là chúng ta phải cập nhật các giá trị state bất cứ lúc nào chúng ta nhập vào các trường này.
Được chứ.Cách đơn giản nhất để làm điều này là tạo một trình xử lý cho mỗi trường input này, trình xử lý này sẽ cập nhật state bất kỳ khi nào xảy ra sự kiện thay đổi.
Hãy tiếp tục và thêm phần sau ngay bên dưới các đối tượng state:
Điều này diễn ra sự kiện mà chúng ta nhận được từ onChange.Về cơ bản chúng ta đang cập nhật đối tượng này và sau đó lưu nó trở lại state.
Chúng ta sẽ sao chép các giá trị cũ bằng cách thực hiện dấu ba chấm, còn được gọi là toán tử chênh lệch.Và sau đó, chúng ta sẽ chỉ nhập các giá trị và thêm dấu phẩy.
Tiếp theo, chúng ta sẽ nói rằng firstName sẽ bằng event.target.value.chúng ta muốn thêm điều này vào input của chúng ta.Vì vậy, trong JSX của chúng ta trong input cho tên, chúng ta sẽ lấy một dòng mới ở đâu đó (ở bất kỳ đâu, điều đó không thực sự quan trọng) và thêm thuộc tính onChange như sau:
Bây giờ, nếu chúng ta truy cập trình duyệt của mình và bắt đầu nhập, bạn có thể thấy rằng mọi thứ hoạt động.Phần còn lại của chúng không hoạt động vì chúng ta chưa thêm trình xử lý cho chúng.chúng ta sẽ xem xét điều đó trong một phút.
Chỉ để tóm tắt lại những gì đang xảy ra: bất cứ khi nào chúng ta nhập vào ô này, sự kiện onChange sẽ xảy ra cho mọi lần nhấn phím.Điều này được gọi mọi lúc.
Sự kiện được React hooks chuyển vào và chúng ta muốn cập nhật đối tượng state của mình.Vì vậy, để làm điều đó, chúng ta gọi hàm setValues và truyền vào một đối tượng mới với các giá trị được cập nhật.
Bây giờ, chúng ta chỉ muốn làm điều tương tự cho lastName và email.Thêm một trình xử lý khác cho mỗi:
Bây giờ là thời điểm của sự thật.Mọi thứ đang hoạt động hay chúng ta đã làm hỏng thứ gì đó trong quá trình?Hãy thử tìm nó và xem.Điền vào một số dữ liệu và các trường input sẽ hoạt động ngay bây giờ.
Mặc dù các trường input của chúng ta đang hoạt động, chúng ta vẫn gặp một vấn đề nếu chúng ta nhập nội dung trong biểu mẫu và cố gắng gửi, nó sẽ không làm được gì cả.Nó sẽ chỉ làm mới trang và tất cả dữ liệu biểu mẫu của React Hooks sẽ bị mất.
Hiển thị thông báo thành công
Sau khi nhấp vào đăng ký, nó sẽ hiển thị thông báo thành công nếu biểu mẫu hợp lệ.Những gì chúng ta muốn làm là truy cập JSX của chúng ta và ngay bên dưới biểu mẫu thêm một div mới.Một lần nữa, tôi đã thêm các lớp cho bạn để có một thông báo thành công:
<div class='success-message'>Success! Thank you for registering</div>
Tất nhiên, bây giờ, điều này sẽ không đi đến đâu.Nó chỉ giả vờ rằng chúng ta đã gọi một máy chủ hoặc một điểm kết thúc ở đâu đó.Và nó quay lại với một thông báo thành công, vì vậy chúng ta sẽ hiển thị thông báo này cho người dùng.
Nhưng hiện tại nó xuất hiện mọi lúc.Những gì chúng ta muốn là chỉ hiển thị điều này nếu người dùng đã gửi biểu mẫu bằng React Hooks thành công.
Vì vậy, chúng ta sẽ thêm một đối tượng state khác như sau:
Chúng ta sẽ giữ phần này tách biệt với các giá trị vì nó là một phần khác của biểu mẫu.Không muốn trộn mọi thứ vào đây và gây ra toàn bộ kết xuất lại.Điều này sẽ cho chúng ta biết liệu biểu mẫu đã được gửi hay chưa.
Ban đầu, nó sẽ được đặt thành false vì lần đầu tiên người dùng truy cập vào trang, nó sẽ không được gửi.
Và bây giờ, chúng ta chỉ muốn thực hiện một số nội dung thông minh trong JSX để nói, “Nếu được gửi là đúng, thì chúng ta muốn hiển thị thông báo thành công.”
Cập nhật dòng mà chúng ta vừa thêm vào như sau:
{showSuccess && <div class='success-message'>Success! Thank you for registering</div>}
Chúng ta sẽ gói gọn thông điệp thành công của mình trong một toán tử bậc ba.Về cơ bản, đó là một câu lệnh if viết tắt cho phép chúng ta hiển thị động mọi thứ trên trang.
Giờ đây, thông báo thành công sẽ chỉ xuất hiện nếu showSuccess là đúng.Như bạn có thể thấy bây giờ trong trình duyệt, điều này đã biến mất.
Nếu chúng ta quay trở lại đối tượng state của chúng ta để submitted và thay đổi điều này thành true, nó sẽ xuất hiện lại.Và nó có
Chúng ta sẽ thay đổi điều này trở lại thành false.Và sau đó, chúng ta sẽ làm mới Chrome của mình và chỉ cần xem điều gì sẽ xảy ra ngay bây giờ.
Chúng ta chưa cho nút đăng ký hoặc biểu mẫu biết điều gì sẽ xảy ra trên hội nghị, vì vậy nó vẫn sẽ làm mới trang.Bây giờ, chúng ta chỉ cần một trình xử lý mới để xử lý việc nhấp vào nút đăng ký.
Nếu chúng ta chuyển sang trình xử lý sự kiện của mình và thêm những thứ sau:
event.preventDefault sẽ ngăn quá trình làm mới xảy ra mà chúng ta đã thấy.
Chúng ta sẽ thêm một số logic nữa vào đây trong một phút nữa về xác thực và các thứ.Nhưng hiện tại, chúng ta chỉ nói “setSubmitted” là đúng.
Tiếp theo, chúng ta cần yêu cầu biểu mẫu gọi hàm này khi nó được gửi.Cập nhật JSX để bao gồm thuộc tính onSubmit trong thẻ biểu mẫu như sau:
<form class='register-form' onSubmit={handleSubmit}>
//... other code
</form>
Bây giờ nếu chúng ta chạy mã trên trình duyệt, bấm vào nút đăng ký, thông báo hiện ra.
Thêm Validation và hiển thị thông báo lỗi
Biểu mẫu của chúng ta cho đến nay trông rất ổn, nhưng chúng ta thiếu một thành phần quan trọng của bất kỳ biểu mẫu nào và đó là xác thực.Nếu chúng ta xem xét ví dụ làm việc của mình, nếu tôi gửi điều này với bất kỳ trường trống nào, một lỗi sẽ xuất hiện cho biết, “Vui lòng nhập thông tin chi tiết của bạn”.
Bên dưới mỗi input, chúng ta sẽ thêm một <span> sẽ chứa thông báo lỗi.JSX của bạn sẽ trông giống như sau:
<input
id="first-name"
class="form-field"
type="text"
disabled={showSuccess}
placeholder="First Name"
name="firstName"
value={values.firstName}
onChange={handleInputChange}
/>
<span id="first-name-error">Please enter a first name</span>
<input
id="last-name"
class="form-field"
type="text"
placeholder="Last Name"
name="lastName"
value={values.lastName}
onChange={handleInputChange}
/>
<span id="last-name-error">Please enter a last name</span>
<input
id="email"
class="form-field"
type="text"
placeholder="Email"
name="email"
value={values.email}
onChange={handleInputChange}
/>
<span id="email-error">Please enter an email address</span>
Bạn có thể thấy những lỗi này luôn xuất hiện, bởi vì chúng ta không có bất kỳ logic điều kiện nào cho biết “không xuất hiện”.
Bây giờ, chúng ta chỉ muốn các thông báo lỗi này hiển thị nếu nút đăng ký đã được nhấp.
Quay lại code. Chúng ta muốn thêm một số logic có điều kiện vào và xung quanh các thông báo lỗi để chúng chỉ xuất hiện nếu nút đã được nhấp và trường trống:
{submitted && !values.firstName && <span id='first-name-error'>Please enter a first name</span>}
Những gì chúng ta đang làm ở đây là kiểm tra xem biểu mẫu đã được gửi và đối tượng state firstName có trống không.Nếu vậy, chúng ta muốn hiển thị thông báo lỗi.Một lần nữa, chúng ta chỉ sử dụng một toán tử bậc ba, không có gì lạ!
Làm tương tự cho các lỗi khác:
{submitted && !values.lastName && <span id='last-name-error'>Please enter a last name</span>}
//...other code
{submitted && !values.email && <span id='email-error'>Please enter an email address</span>}
Nếu chúng ta để trống biểu mẫu và nhấp vào đăng ký, lỗi sẽ xuất hiện. Nếu chúng ta bắt đầu nhập mọi thứ, chúng ta có thể thấy rằng lỗi sẽ biến mất. Và nếu chúng ta xóa những gì chúng ta đã nhập, lỗi sẽ quay trở lại.
Hãy thử và gửi một số thứ. Được rồi, vì vậy điều này có vẻ đang hoạt động.
Điều cuối cùng chúng ta muốn làm là đảm bảo rằng thông báo thành công này chỉ xuất hiện nếu biểu mẫu hợp lệ. Hãy tiếp tục và thêm một giá trị state mới:
const [valid, setValid] = useState(false);
Điều này được sử dụng để cho chúng ta biết liệu biểu mẫu của chúng ta có hợp lệ hay không – hãy nhớ rằng, sử dụng các đối tượng state là một cách tốt để giữ “state” của các phần khác nhau trong ứng dụng của bạn (ai có thể đoán được?).
Thông báo thành công sẽ chỉ xuất hiện nếu đã gửi là đúng và theo dõi cũng đúng. Vì ban đầu chúng ta đã đặt giá trị hợp lệ là false, nên nó sẽ không hiển thị.
Trong hàm handleSubmit của chúng ta, chúng ta muốn nói rằng giá trị là true nếu một biểu mẫu hợp lệ. Chúng ta có thể làm điều này bằng cách kiểm tra từng giá trị state của chúng ta cho các trường biểu mẫu, đảm bảo rằng chúng là một giá trị trung thực.
Nếu bất kỳ trường nào trong số này là false, thì valid hợp lệ sẽ vẫn là false.Điều này có nghĩa là div thông báo thành công sẽ không được hiển thị.Hãy xem nó hoạt động.Nếu chúng ta nhấp vào đăng ký mà không có trường, thông báo lỗi của chúng ta sẽ hiển thị.Hãy nhập một số nội dung hợp lệ, nhấn đăng ký và thông báo xuất hiện!
Sai lầm thường được xem là một danh từ mang tính tiêu cực, nhưng bạn hoàn toàn có thể nhìn nhận nó theo hướng tích cực hơn. Đơn giản vì chúng ta luôn mắc lỗi, nên ít nhất hãy biến chúng thành bài học để có thể khắc phục sai lầm.
Không ai là hoàn hảo – chúng ta luôn mắc lỗi và điều hoàn toàn tạo nên con người chúng ta.Chúng ta không sống trong một thế giới hoàn hảo, và chính sự không hoàn hảo là điều khiến cuộc sống trở nên năng động hơn.
Đôi khi, ngay cả một sai sót nhỏ cũng có thể dẫn đến những tổn thất lớn về tài chính, đặc biệt là đối với các bạn lập trình viên ngoài kia.
Nhưng thay vì chỉ cảm thấy tồi tệ khi mắc sai lầm, bạn có thể làm một vài điều để khắc phục sai lầm đó.
1. Học từ sai lầm
Nguyên tắc vàng khi bạn mắc sai lầm là bạn phải học được gì từ đó.
Tôi chắc rằng tất cả các bạn đã nghe qua điều này (và đang nghĩ “Ờ cảm ơn ông, nói điều ai cũng biết”).Nhưng những bạn đã nghe qua khái niệm này đã từng thực sự áp dụng nó chưa?
Ông bà ta có rất nhiều câu ca dao tục ngữ, đại ý là bạn không nên mắc cùng một sai lầm hai lần. Nhưng trên thực tế, mọi người đều có thể mắc những sai lầm giống nhau lặp đi lặp lại.Học hỏi từ sai lầm không đảm bảo rằng bạn sẽ không mắc phải sai lầm tương tự nữa.
Có rất nhiều điều bạn có thể học được từ sai lầm của mình: Nó đã xảy ra như thế nào?Nó đã ảnh hưởng đến gì?Nó nghiêm trọng ra sao?
Những bài học sẽ không bao giờ là đủ cả.
Nhưng điều quan trọng nhất là bạn cố gắng hiểu về sai lầm đó một cách đầy đủ.Ít nhất thì giảm tối thiểu khả năng nó xảy ra lần nữa hoặc khắc phục sai lầm.Và hãy chắc rằng bạn mắc phải sai lầm theo cách hoàn toàn khác lúc đầu.
2. Đưa ra giải pháp thay vì bào chữa
Bất cứ khi nào có chuyện gì đó xảy ra vì một sai lầm, điều đầu tiên mà hầu hết mọi người làm là đưa ra lời bào chữa.Thậm chí còn có một số câu trả lời và đổ lỗi cho qua chuyện, mà họ quên mất điều quan trọng nhất là: giải quyết vấn đề.
Thay vì viện lý do, thì việc tìm giải pháp nên là ưu tiên hàng đầu của bạn.Tất nhiên, có thể có một lý do chính đáng nào đó khiến bạn mắc lỗi, nhưng điều đó có thể đợi cho đến khi bạn tìm ra giải pháp phù hợp.
Hãy sử dụng thời gian của bạn một cách hiệu quả.Khi mọi thứ được xử lý ổn thỏa, bạn có thể giải thích những gì đã xảy ra một cách cẩn thận và đưa ra phân tích để khắc phục sai lầm.
3. Không biết thì không sao, nhưng cố tình lờ đi thì không được
Thường chúng ta mắc sai lầm vì chúng ta không biết điều gì đó.Nhưng những sai lầm kiểu đó có ổn không?
Mọi người mắc sai lầm khi bước vào lãnh thổ không xác định là điều bình thường.Nhưng câu hỏi thực sự bạn cần đặt ra là nếu người đó không biết hoặc không cố gắng biết, bởi vì những điều đó hoàn toàn khác nhau.
Đôi khi trong cuộc sống, chúng ta đi đường tắt và tìm ra cách dễ dàng để thực hiện một điều gì đó.Chẳng có vấn đề gì với việc đấy cả.
Nhưng những gì mọi người thường quên là các phím tắt có thể gây hiểu lầm, và vâng, có thể là từ mạnh ở đây.Mọi người có xu hướng bỏ qua khả năng xảy ra sự cố và không nghĩ nhiều về hậu quả.
Khi ai đó nói “Tôi không biết”, điều này thường được dịch thành “Tôi không buồn biết.”Mọi người có xu hướng tìm cách dễ dàng để làm điều gì đó và tiếp tục không biết về những gì họ đang làm.Họ không buồn nhìn sâu hơn vì mọi thứ có vẻ ổn.
Khi bạn vô tình gây ra sai lầm vì bạn thực sự không biết điều gì đó, điều đó là tốt.Nhưng khi bạn gây ra sai lầm do cố tình thiếu hiểu biết, điều đó không ổn.Bởi vì cho dù bạn mắc phải sai lầm bao nhiêu lần, bạn cũng sẽ không bao giờ rút ra được bài học từ nó.
4. Đừng quên chia sẻ sai lầm của bạn
Thường khi chúng ta mắc lỗi, chúng ta chỉ cố gắng khắc phục sai lầm và tiếp tục học tập từ đó.Chúng tôi quên rằng điều rất quan trọng là phải chia sẻ những sai lầm của chúng tôi.
Chúng ta có thể bối rối trước viễn cảnh trông thật ngớ ngẩn.Nhưng may mắn thay, lợi ích vượt xa điều đó.
Đầu tiên và quan trọng nhất, nó sẽ giúp người khác tránh mắc phải những sai lầm như bạn đã làm.Và trong sâu thẳm họ sẽ thực sự biết ơn vì điều đó.
Không chỉ vậy, chia sẻ những sai lầm của bạn có thể mang lại cho bạn một cái nhìn mới và khác biệt về những gì người khác có thể nghĩ về nó.Họ có thể cho bạn một góc nhìn mới hoặc có thể là một giải pháp tốt hơn để xử lý nó.
Đừng quên chia sẻ những sai lầm của bạn, bởi vì chia sẻ là quan tâm.
5. Đúc kết từ hậu quả
Hãy nhớ rằng mọi sai lầm đều đi kèm với hậu quả.Chúng có thể gây tổn thất tài chính, hoặc thậm chí ảnh hưởng đến uy tín của bạn.
Cần phải xác định rõ ràng và hiểu rõ hậu quả, vì hiểu rõ hậu quả sẽ trở thành yếu tố răn đe khi tiếp cận bất kỳ tình huống nào.Nó cũng sẽ giúp bạn xem xét tốt hơn cách bạn sẽ giải quyết vấn đề.
Đôi khi, hậu quả có thể ở lại với bạn trong một thời gian dài.Và bạn phải chịu đựng nó và chịu mọi hậu quả vì đó là trách nhiệm của bạn.
Nhưng dù hậu quả có lớn đến đâu thì cũng đừng quá khắt khe với bản thân.Giữ một tinh thần tốt và sự tích cực là chìa khóa để giải quyết hậu quả.
Kết bài
Sai lầm không phải là dấu chấm hết cho mọi thứ.Cuộc sống vẫn tiếp diễn và mọi thứ không ngừng vận động.Một số thứ bị bỏ lại phía sau và những thứ mới phát sinh.
Điều tốt nhất bạn có thể làm với bất kỳ sai lầm nào là học hỏi từ nó một cách tốt nhất có thể và biến nó thành một sai lầm thành công.
Cuộc sống là một hành trình quá dài để bạn có thể mắc kẹt vì một sai lầm.Hãy tiếp tục và tận hưởng chuyến đi.