Làm Gì Để Vượt Qua Khủng Hoảng Sau Khi Trượt Phỏng Vấn?
Trượt phỏng vấn là câu chuyện không của riêng ai. Mỗi người có thể trượt phỏng vấn vì nhiều lý do khác nhau, tuy nhiên đa số mọi người sẽ cảm thấy thất vọng hoặc buồn bã về bản thân, nhất là với những bạn sinh viên mới ra trường chưa có nhiều kinh nghiệm. Bài viết này sẽ giúp bạn tìm được hướng đi đúng đắn và hợp lí hơn cho bản thân với việc nên làm gì khi trượt phỏng vấn.
Nên làm gì để vượt qua khủng hoảng sau nhiều lần trượt phỏng vấn?
Đối diện với cảm giác thất vọng và tìm cách vượt qua
Thất vọng chắc chắn là cảm xúc biểu hiện rõ ràng nhất sau khi bạn nhận được kết quả trượt phỏng vấn. Rất nhiều suy nghĩ hiện ra trong đầu rằng bản thân vẫn còn quá kém cỏi, năng lực chuyên môn mình vẫn chưa đủ cứng, đâu là thiếu sót khiến mình không thể thông qua buổi phỏng vấn,… Nhiều câu hỏi được đặt ra một cách liên tiếp để chứng minh cho việc bạn đang lo lắng và thiếu niềm tin vào bản thân.
Nhưng trượt phỏng vấn không hề chứng minh được bất kỳ điều gì về năng lực bản thân của bạn cả. Nó chỉ đơn thuần là những gì bạn có thể đáp ứng vẫn chưa phù hợp với yêu cầu của công ty mà thôi. Do đó, hãy thật bình tĩnh và tìm cách vượt qua chính mình. Hoang mang hay lo lắng sẽ chỉ khiến bạn mất phương hướng hơn.
Trước khi bắt tay vào tìm kiếm một công việc mới, bạn hãy cho bản thân được thư giãn và nghỉ ngơi nhiều hơn một chút. Bạn có thể dành thời gian làm những gì mình thích để thư giãn tinh thần trước khi tìm kiếm cho mình một cơ hội mới, như vậy chắc chắn về mặt tâm lý bạn sẽ làm tốt hơn rất nhiều. Đây chính là câu trả lời chính xác cho vấn đề nên làm gì sau khi trượt phỏng vấn.
Đánh giá lại toàn bộ những vấn đề mình đang gặp phải
Trước khi bắt tay vào tìm kiếm một công việc mới, tốt hơn hết bạn nên dành thời gian để đánh giá lại một cách tổng quan về những gì mà đã làm được và chưa làm được trong hành trình tìm việc vừa rồi. Hãy nhìn nhận một cách thẳng thắn về những gì mình vẫn chưa làm được và nên khắc phục nó như thế nào.
Để có thể đánh giá một cách tốt nhất và có sự cải thiện cho sau này, bạn có thể tham khảo ý kiến từ những người xung quanh hoặc những người làm trong ngành nhân sự mà bạn quen biết. Người khác sẽ cho bạn cái nhìn khách quan về năng lực bản thân. Đặc biệt với những ai làm trong lĩnh vực nhân sự, vì họ thường xuyên làm việc với các ứng viên nên có thể dễ dàng trong việc giúp bạn tìm ra và cải thiện những vấn đề mình chưa làm tốt. Ý kiến của người khác thì luôn khách quan hơn chính vì thế đừng ngần ngại đặt câu hỏi để giúp bản thân trở nên tốt hơn bạn nhé!
Sau khi đã cho bản thân khoảng thời gian thư giãn thoải mái về đầu óc cũng như tìm ra được điểm yếu và điểm mạnh của bản thân, bạn hãy tập trung dành thời gian để tìm kiếm những công việc mới. Công việc không bao giờ là khan hiếm trên thị trường cả, điều quan trọng là bạn có biết tận dụng đúng thời cơ và dành hết sức mình cho cho một công việc, một vị trí mới hay không.
Bên cạnh đó, hãy đọc kỹ các mô tả công việc được đăng tuyển để xem mình có thể đáp ứng được bao nhiêu phần trăm khả năng trong số đó. Tốt hơn hết là từ 70% trở lên, nếu thấp hơn mức này bạn có thể thấy rằng bản thân chưa phù hợp với định hướng của công ty nên tốt hơn hết là không nên ứng tuyển. Việc không đạt kỳ phỏng vấn phần nhiều cũng là do mục tiêu của công ty và của ứng viên chưa thật sự tương xứng với nhau.
Đừng bao giờ cảm thấy khó khăn hay chán nản sau khi trượt phỏng vấn, vì biết đâu được bạn sẽ tìm được những cơ hội mới tốt đẹp hơn so với vị trí mà mình đã từng ứng tuyển. Hãy luôn giữ một tinh thần mạnh mẽ và lạc quan để tìm kiếm cho mình những cơ hội, những công việc mới mà bản thân thật sự cảm thấy yêu thích và phù hợp. Khi một cánh cửa đóng lại sẽ có cánh cửa khác mở ra, hãy tỉnh táo để nắm giữ “cánh cửa” mới này cho mình bạn nhé.
Bài viết được sự cho phép của tác giả Kien Dang Chung
Video trong bài viết
Ứng dụng Todo List của chúng ta đã có hai trang, một trang danh sách các công việc và một trang chi tiết cho công việc cụ thể. Hai trang này tương ứng với hai view là index.blade.php và show.blade.php nằm trong thư mục resources/views/todos. (Bạn nào chưa có source thì tải về nhé, source của bài trước ở đây). Nếu các bạn để ý trong hai file view này có rất nhiều đoạn code giống nhau, vậy làm thế nào chúng ta mô đun hóa và sử dụng lại các đoạn code chung này?
Các website hiện nay thường có rất nhiều trang và có một vài bố cục chung. Ví dụ, như trang All Laravel mà bạn đang xem, ở bất kỳ trang nào chúng ta cũng thấy có 2 phần chung:
Header bao gồm logo, menu, phần các bài viết phổ biến.
Sidebar: bao gồm công cụ tìm kiếm, các thẻ, bài viết phổ biến.
Footer: Thông tin liên hệ, đăng ký nhận tin bài.
Bố cục ứng dụng chung có những ưu điểm như sau:
Những phần chung này sẽ được mô đun hóa đưa ra một file riêng gọi là file layout (bố cục chung). Các file muốn có bố cục này chỉ cần “kế thừa” lại layout này.
Khi cần thay đổi nội dung chung, chúng ta không cần thay đổi tất cả các trang mà chỉ cần thay đổi trong phần bố cục chung. Ví dụ, khi thay đổi Logo mới chẳng hạn, chúng ta chỉ cần vào file layout thay đổi và nó sẽ áp dụng cho tất cả các trang kế thừa bố cục này.
Xây dựng bố cục với Laravel Blade
Laravel Blade cho phép xây dựng file layout và các view sẽ kế thừa lại layout này. Quay lại hai view index và show trong ứng dụng Todo List, chúng ta thấy có rất nhiều phần chung, chúng ta tạo file chứa bố cục này resources/views/layouts/app.blade.php (đặt tên thế nào cũng được miễn là tên diễn giải được ý nghĩa).
Trong file này chúng ta thấy có một số code trông khá lạ như sau:
yield(‘title’)
yield(‘content’)
Diễn giải code, chúng ta thấy có tiêu đề các trang khác nhau (phần title) và phần nội dung trang (phần content) khác nhau do vậy, yield(‘title’) và yield(‘content’) chính là nơi hiển thị các phần khác nhau đó.
Mẹo: Tất cả các phần có nội dung thay đổi được đưa vào một phần riêng với lệnh yield(‘ten_vung_chung’).
Khi đó ở các trang (view) cần “kế thừa” bố cục này, chúng ta sẽ sử dụng câu lệnh extends. Cấu trúc lại code resources/views/todos/index.blade.php:
@extends('layouts.app')
@section('title')
Todos List
@endsection
@section('content')
<h1 class="text-center my-5">TODOS PAGE</h1><div class="row justify-content-center"><div class="col-md-8"><div class="card card-default"><div class="card-header">
Todos
</div><div class="card-body"><ul class="list-group">
@foreach($todos as $todo)
<li class="list-group-item">
{{ $todo->name }}
<a href="/todos/{{ $todo->id }}"class="btn btn-primary btn-sm float-right mr-2">View</a></li>
@endforeach
</ul></div></div></div></div>
@endsection
Trong hai view này, để kế thừa bố cục chung ứng dụng chúng ta dùng câu lệnh extends(‘ten_bo_cuc’), chú ý là một ứng dụng có thể có nhiều bố cục chung khác nhau. Tên bố cục chứa cả đường dẫn đến file bố cục và phân cách bởi dấu chấm, ví dụ ở đây là layouts.app tức là file app.blade.php trong thư mục layouts với thư mục mặc định là resources/views.
Tiếp đến, các phần nội dung khác nhau được định nghĩa bằng câu lệnh yield ở trong layout sẽ được sử dụng trong view và nằm giữa @section(ten_vung_dinh_nghia_trong_yield) và @endsection.
Quay lại ứng dụng và kiểm tra các trang, bạn sẽ thấy ứng dụng khi thay đổi này không khác gì so với ứng dụng của bài học trước (bài số 9). Tại sao phải thực hiện những công việc ở trên?
Thêm menu cho ứng dụng
Trở lại với câu hỏi ở phần trước, tại sao chúng ta lại đưa toàn bộ phần code chung ra file layouts/app.blade.php? Ứng dụng hoạt động trên các trang index và show đã rất ok, tuy nhiên chúng ta cần một menu chung cho toàn bộ ứng dụng để có thể chuyển hướng nhanh chóng đến một trang nào đó. Nếu như chưa có layouts/app.blade.php chúng ta sẽ phải đến từng trang (view) cụ thể và thêm menu vào, thật là mất nhiều công sức, chưa kể là mỗi khi cần thay đổi, chúng ta lại mất nhiều công sức hơn nữa và rất dễ bỏ sót những vị trí cần thay đổi.
Công việc dễ dàng hơn nhiều với file bố cục chung, chúng ta chỉ việc thêm menu vào file layouts/app.blade.php và các view kế thừa lại bố cục này sẽ tự động có thanh menu. Nội dung layouts/app.blade.php sẽ thay đổi như sau:
Không cần thay đổi gì hai index và show trong thư mục view resources/views/todos nhưng khi chạy ứng dụng bạn thấy đấy chúng ta đã có menu cho cả hai view này.
Bài viết được sự cho phép của blogchiasekienthuc.com
DNS là một trong những thành phần rất quan trọng của mạng Internet. Và nếu như bạn đã từng loay hoay với việc truy cập vào Facebook khi bị chặn thì chắc chắn bạn đã tìm hiểu qua về DNS rồi đúng không.
Và trong quá trình sử dụng máy tính, không biết các bạn thế nào chứ mình thì đôi khi gặp phải lỗi DNS Server is not responding khiến mình không tài nào kết nối vào Internet được.
Vậy nên trong bài viết này mình sẽ tổng hợp lại những cách hiệu quả nhất để khắc phục thành công lỗi DNS Server is not responding khó chịu này nha.
Xui xui cho bạn thì sẽ xuất hiện lỗi DNS như hình bên dưới đây 🙂
#1. Khởi động lại máy tính
Đối với mình, điều đầu tiên mà mình làm nếu có bất kì lỗi nào xảy ra với hệ điều hành Windows đó là khởi động lại máy.
Nghe thì có vẻ hơi nhạt, hơi vô lí nhưng đôi khi nó lại có tác dụng không tưởng đó các bạn. Chính vì vậy, bạn cứ khởi động lại máy tính đó trước khi thực hiện các bước tiếp theo nhé.
Đừng đùa với cách làm này nhé, các lỗi thường gặp như máy tự tự nhiên bị mất âm thanh, không chạy được phần mềm, máy tính tự nhiên giật lag lạ thường, máy in tự nhiên không in được… thì khởi động lại sẽ là phương án khá là hay đấy 🙂
#2. Thay đổi DNS Server
+ Bước 1: Mở hộp thoại Run bằng cách bấm tở hợp phím Windows + R => sau đó nhập ncpa.cpl => và nhấn Enter.
+ Bước 2: Sau đó bạn tìm đến đúng kết nối mạng Internet mà bạn đang dùng. Ví dụ như của mình ở đây là mạng Wi-Fi đó (có cột sóng ở bên dưới icon Computer).
=> Sau đó bạn nhấn chuột phải vào mang đó => và chọn Properties.
+ Bước 3: Sau đó bạn nháy đúp chuột vào phần Internet Protocol Version 4 (TCP/IPv4) để chúng ta vào phần thiết lập.
+ Bước 4: Bây giờ bạn tick chọn Use the following DNS Server addresses. Tiếp theo bạn có thể chỉnh các DNS sau:
+ Bước 5: Sau khi đã xong xuôi hết thì bạn bấm OK => Cuối cùng bạn tắt mạng đi và bật lại để thử nha.
NOTE: Để tìm hiểu thêm về phần thiết lập này thì bạn có thể tham khảo thêm bài viết này, chắc chắn nó sẽ rất hữu ích cho bạn!
#3. Cài đặt lại Driver mạng
Lưu ý: Tải Driver mạng trước khi cài đặt lại nha các bạn. Mình đề xuất với các bạn sử dụng phần mềm 3DP NET, một phần mềm có thể cân được mọi thể loại máy tính hiện nay
Nhưng tất nhiên là bạn hãy thử qua phương pháp bên dưới đã, nếu vẫn không đường thì mới dùng đến tuyệt chiêu cuối 3DP NET nhé !
+ Bước 1: Bạn nhấn tổ hợp phím Windows + X => sau đó bấm chọn Device Manager => Bạn bấm vào Network Adapters.
Một cách mở Device Manager khác là nhấn chuột phải vào This PC => chọn Manage => sau đó chọn Device Manager
Tiếp theo, bạn nháy đúp chuột vào adapter mạng đang sử dụng, ví dụ như của mình ở đây đang sử dụng mạng Wi-Fi thì nó là Intel(R) Dual Band Wireless-AC 8230
+ Bước 2: Sau đó bạn chuyển qua tab Driver như hình bên dưới.
+ Bước 3: Tiếp theo bạn bấm vào Uninstall Device, nhớ tick vào Delete the driver software for this device => bấm Uninstall để thực hiện gỡ bỏ Driver hiện tại.
Hoặc bạn có thể làm theo cách nhanh hơn đó là nhấn chuột phải vào mạng bạn đang sử dụng => và chọn Uninstall device (hình ảnh bổ sung bởi Admin):
+ Bước 4: Sau đó bạn nhấn chuột phải lại vào kết nối mạng như hình bên trên => sau đó chọn Scan for hardware changes để máy tính cài đặt lại Driver.
Hoặc là bạn có thẻ khởi động lại máy tính cũng được, lúc này ta có hai trường hợp sau:
Nếu máy tính vào mạng bình thường thì bạn thành công rồi đó.
Nếu máy tính vẫn bị lỗi trên hoặc không nhận Driver thì bạn tải lại Driver mới. Để tải Driver chuẩn nhất theo đúng hãng máy tính của bạn thì bạn xem bài viết này, còn nếu không có nhiều kinh nghiệm thì cứ dùng 3DP NET nha các bạn.
#4. Tắt tường lửa và phần mềm diệt virus
Tường lửa và phần mềm diệt virus đều là bức tường thành bảo vệ máy tính của bạn.
Nhưng đôi khi chính nó lại gây ảnh hưởng đến Internet của bạn. Chính vì vậy, hãy thử tắt tường lửa và phần mềm diệt virus, có thể sẽ tạm thời sửa được lỗi DNS Server is not responding gây khó chịu này đó.
+ Bước 2: Cuối cùng bạn khởi động lại máy để áp dụng thay đổi nha.
#6. Khởi động máy tính ở chế độ Safe Mode
Safe Mode giúp bạn khởi động máy tính với các phần mềm và trình điều khiển (Driver) cơ bản nhất. Đôi khi lỗi DNS này xảy ra do phần mềm hoặc trình điều khiển của một phần cứng nào đó xung đột với nhau.
+ Bước 1: Để truy cập vào chế độ Safe Mode của máy tính thì bạn bấm phím Windows trên bàn phím (cạnh phím ALT) => sau đó bấm vào nút Power, giữ phím Shift => và bấm Restart.
+ Bước 2: Bạn bấm chọn Troubleshoot.
+ Bước 3: Tiếp theo bạn chọn Advanced options.
+ Bước 4: Sau đó bạn bấm chọn Startup Settings => và bấm Restart.
Tiếp theo bạn bấm 5 hoặc F5 để vào chế độ Safe Mode with Networking (đây là chế độ Safe Mode có Internet).
Nếu mạng bình thường trong chế độ này thì đương nhiên là do phần mềm của máy tính gây ra lỗi DNS rồi. Bây giờ bạn chỉ việc tìm phần mềm gây ra lỗi và gỡ cài đặt thôi.
Ngoài cách truy cập vào Safe Mode để kiểm tra máy tính có mạng hay không thì nếu bạn có sẵn một chiếc USB BOOT thì bạn cũng có thể truy cập vào Mini Windows để kiểm tra một cách dễ dàng.
Mà mình đề xuất với bạn bản NHV BOOT, bạn có thể tạo sẵn một chiếc USB BOOT cứu hộ chuyên nghiệp để sử dụng khi cần nhé 🙂
#7. Khởi động lại Moderm hoặc Router
Nếu tất cả các thiết bị kết nối với Moderm đều bị lỗi như trên thì nguyên nhân là do Moderm hoặc nhà cung cấp mạng của bạn đang có vấn đề.
Đầu tiên thì bạn hãy ra đằng sau Moderm, tìm nút Restart để khởi động lại. Hoặc không thì bạn có thể rút dây nguồn ra khoảng 10s sau đó cắm lại. Sau đó kiểm tra lại nhé !
#8. Reset lại Modem hoặc Router mà bạn đang kết nối
Nếu những cách bên trên không có tác dụng thì bạn có thể thử Reset Modem. Cách làm này thì hơi nâng cao một chút, bạn phải có một chút kiến thức về kỹ thuật thì mới có thể làm được.
Tuy nhiên mình nói trước, hiện giờ việc cấu hình Modem đã khác khá nhiều rồi, vì nhiều dòng Modem đời mới nên giao diện khác khá nhiều.
Vậy nên, nêu bạn không am hiểu thì nên chuyển ngay sang bước số #9 bên dưới đây 🙂
#9. Liên hệ CSKH của nhà cung cấp dịch vụ
Đây chính là cách cuối cùng nếu như tất cả các cách trên đều không có tác dụng hoặc không triệt để. Bạn hãy liên hệ đến CSKH của nhà cung cấp dịch vụ để họ có thể sử được triệt để lỗi này cho bạn.
Viettel: Tổng đài hỗ trợ là 1800 8168
VNPT: Tổng đài hỗ trợ là 1800 1166
FPT: Tổng đài hỗ trợ là 1900 6600 hoặc 1800 6000
Nhà mạng sẽ có trách nhiệm Fix lỗi đường truyền giúp bạn, bạn nộp tiền mạng hàng tháng nên được quyền lợi này nhé. Nhưng tất nhiên đó là trong trường hợp bạn là người đứng ra đăng ký dịch vụ Internet.
#10. Một vài Tips nhỏ khác để xác định và khắc phục lỗi DNS Server này
Bạn hãy thử sử dụng một trình duyệt web khác xem sao.
Nếu máy tính bạn đang sử dụng mạng Wi-Fi để kết nối thì giờ thử chuyển sang mạng dây để kết nối xem có được không, hoặc ngược lại, nếu đang dùng mạng dây thì chuyển thử sang Wi-Fi.
Trên đây là toàn bộ những cách và những bước để sửa lỗi The DNS Server isn’t responding trong quá trình sử dụng máy tính.
Bạn đã bao giờ gặp phải lỗi như thế này chưa? và nếu đã gặp thì bạn đã sửa nó như thếnào? Hãy chia sẻ lại cách làm của bạn để am em cùng học hỏi thêm nhé.
Chúc các bạn thành công, và mong mọi người hãy comment để ủng hộ bài viết của mình [đây là một trong những bài viết đầu tiên của mình trên Blog :)], có như vậy mình mới hoàn thiện hơn ở các bài viết sau nha. Thank you !
Tôi không thể đưa ra một đánh giá toàn diện về DDD trong một bài viết trên blog. Có quá nhiều khái niệm quan trọng liên quan đến DDD. May mắn thay, đó cũng không phải là mục tiêu ở đây. Tuy nhiên, những gì tôi sẽ làm là liệt kê các khái niệm DDD mà tôi thấy có liên quan đến cách tôi muốn tổ chức mã và cách tôi nghĩ về Kiến trúc: các khái niệm hệ thống rộng tạo thành nền tảng cho phát triển tính năng.
Trong bài viết, tôi sẽ nói về:
Ubiquitous language (Ngôn ngữ chung)
Layers Bounded contexts
Anti-Corruption Layer
Shared Kernel
Generic Subdomain
UBIQUITOUS LANGUAGE
Một vấn đề thường xảy ra trong phát triển phần mềm, xoay quanh sự hiểu biết về mã nguồn, nó là gì, nó làm gì, nó như thế nào, tại sao nó lại … nó thậm chí còn phức tạp hơn để hiểu mã nguồn khi nó sử dụng một thuật ngữ khác với thuật ngữ mà các chuyên gia về nghiệp vụ (domain expert) sử dụng. Ví dụ, nghiệp vụ chuyển tiền trong ngân hàng được các chuyên gia gọi là remittance, tuy nhiên khi các developer nghe được từ “chuyển tiền”, họ lại để trong code là money transfer, điều này có thể gây ra nhiều nhầm lẫn khi thảo luận về ứng dụng. Tuy nhiên, hầu hết sự mơ hồ này có thể được giải quyết bằng cách đặt tên đúng các lớp và các phương thức, làm cho chúng thể hiện một đối tượng và phương pháp nào đó trong ngữ cảnh của nghiệp vụ.
Ý tưởng chính của việc sử dụng một Ngôn ngữ chung (Ubiquitous language) là để giúp cho việc không nhầm lẫn mơ hồ giữa các khái niệm về nghiệp vụ với cách đặt tên, ánh xạ các khái niệm đó ở trong mã nguồn. Code, class, method, properties và đặt tên mô-đun phải phù hợp với ngôn ngữ chung. Nếu cần thì ta có thể refactor (tái cấu trúc) lại mã nguồn để đạt được điều đó, với mục đích chung là thống nhất các thuật ngữ giữa code và nghiệp vụ.
LAYERS
Tôi đã nói về Layers trong một bài viết trước, nhưng tôi sẽ viết lại trong bài viết này từ góc nhìn của DDD:
USER INTERFACE
Chịu trách nhiệm render màn hình người dùng sử dụng để tương tác với ứng dụng và dịch các đầu vào của người dùng vào các lệnh ứng dụng. Điều quan trọng cần lưu ý là “người dùng” có thể là con người nhưng cũng có thể là các ứng dụng khác kết nối với API của chúng ta, tương ứng hoàn toàn với các đối tượng Boundary trong kiến trúc EBI;
APPLICATION LAYER
Dàn xếp các đối tượng domain để thực hiện các tác vụ theo yêu cầu của người dùng hay còn gọi là các use-case. Nó không chứa business logic. Điều này giống với Interactors trong kiến trúc EBI, ngoại trừ Interactors là bất kỳ đối tượng nào không liên quan đến User Interfaces hoặc Entity, và trong trường hợp này, Application Layer chỉ chứa các đối tượng có liên quan đến một use-case. Lớp này là nơi mà Application Services thuộc về, vì chúng là nơi tổng hợp, sử dụng tất cả các loại object khác như repositories, Domain Services, Entities, Value Objects hoặc bất kỳ đối tượng Domain nào để đáp ứng yêu cầu của các use-case.
DOMAIN LAYER
Đây là lớp có chứa tất cả logic nghiệp vụ, Domain Services, Entities, Events và bất kỳ loại đối tượng khác có chứa Logic nghiệp vụ. Rõ ràng nó chính là Entity Object của EBI. Đây là trung tâm, là trái tim của hệ thống. Domain Services sẽ chứa các logic nghiệp vụ không phù hợp với một Entity, thường là kết hợp một số Entity trong việc thực hiện một số công việc liên quan đến nghiệp vụ;
INFRASTRUCTURE
Các khả năng kỹ thuật hỗ trợ các Layers ở trên, ví dụ như persistence hoặc messaging.
Eric Evans, 2003
BOUNDED CONTEXTS
Trong một ứng dụng doanh nghiệp, có thể có rất nhiều model, các khái niệm cũng như số lượng và kích thước của team làm việc trên codebase là rất lớn. Điều này mang lại cho chúng ta hai vấn đề:
Các developer làm việc trên codebase càng lớn thì càng khó nhận thức và hiểu đúng về những gì những đoạn mã đang làm, và do đó có thể tạo ra bug, gây khó khăn trong việc debug, hiểu đúng và ra quyết định được làm theo thế nào.
Các nhiều developer làm việc trên cùng một codebase, càng khó khăn hơn để hợp tác và có một tầm nhìn chung về kỹ thuật và nghiệp vụ của ứng dụng.
Nói cách khác, đó là 2 vấn đề lớn cần giải quyết khi làm việc với các ứng dụng tầm cỡ enterprise.
Giải pháp thông thường cho một vấn đề lớn là chia nhỏ nó thành những phần nhỏ hơn, hay còn gọi là “bounded contexts”. Nơi mỗi phần phục cho những đối tượng người dùng khác nhau. Nói cách khác, trong 1 hệ thống phần mềm doanh nghiệp, nơi mà hệ thống sẽ phục vụ cho rất nhiều đối tượng người sử dụng khác nhau, việc chúng ta nên làm là chia nhỏ hệ thống đó ra thành những hệ thống nhỏ hơn, đơn lẻ về nhiệm vụ, và đối tượng người dùng. Ví dụ hệ thống nhân sự, kế toán, tiền lương. Mỗi hệ thống có 1 ngữ cảnh riêng gọi là “bounded contexts”, nơi mà nó hệ thống con đó chỉ có hiểu biết về ngữ cảnh, nghiệp vụ nó đảm nhiệm.
Two subsystems commonly serve very different user communities.
Eric Evans 2014, Domain-Driven Design Reference
Các bounded contexts xác định một ngữ cảnh áp dụng một phần riêng biệt của mô hình nghiệp vụ. Việc cô lập này có thể đạt được bằng cách tách các logic kỹ thuật, tách biệt codebase, tách biệt giản đồ cơ sở dữ liệu (database schema) và về tổ chức team. Mức độ cô lập bounded context, như thường lệ, phụ thuộc vào tình hình thực tế: nhu cầu và khả năng chúng ta có.
Một điểm thú vị, đây không phải là một khái niệm hoàn toàn mới. Ivar Jacobson đã viết về các hệ thống con (subsystems) trong cuốn sách của mình (Object-Oriented Software Engineering: A Use Case Driven Approach), trở lại vào năm 1992, mười một năm trước Eric Evans!
Ivar Jacobson, 1992
Khi đó, ông đã có một vài ý tưởng rất cụ thể về chủ đề này:
Hệ thống do vậy bao gồm một số các hệ thống con có thể chứa các hệ thống con của chính nó. Ở dưới cùng của phân cấp như vậy là các đối tượng phân tích (analysis objects). Các hệ thống con là một cách để cấu trúc hệ thống cho việc phát triển và bảo trì.
Nhiệm vụ của các hệ thống con là đóng gói các đối tượng sao để làm giảm đi sự phức tạp. Tất cả các đối tượng đảm nhiệm các phần cụ thể của chức năng sẽ được đặt trong cùng một hệ thống con
Mục đích là để có một gắn kết chức năng mạnh mẽ trong một subsystem và một sự liên kết lỏng lẽo giữa các subsystem (ngày nay được gọi là low coupling and high cohesion)
[Một hệ thống con] nên tốt hơn nên được sử dụng bởi chỉ một actor, vì thay đổi thường được gây ra bởi một actor.
[…] bắt đầu bằng cách đặt các đối tượng điều khiển trong một subsystem, và sau đó đặt các đối tượng thực thể liên kết chặt chẽ (strongly coupled) và các đối tượng giao diện (interface objects) trong cùng một subsystem.
Tất cả các đối tượng có gắn kết chức năng mạnh mẽ (strong mutual functional coupling) sẽ được đặt trong cùng một subsystem […]
Liệu những thay đổi trong một đối tượng dẫn đến những thay đổi trong đối tượng kia? (Điều này bây giờ được gọi là Nguyên tắc The Common Closure Principle – Classes được xuất bản bởi Robert C. Martin trong bài báo “Granularity” năm 1996, 4 năm sau cuốn sách Ivar Jacobson)
Liệu chúng có giao tiếp với cùng một actor?
Có phải cả hai đều phụ thuộc vào một đối tượng thứ ba, chẳng hạn như một interface object hay một entity? Liệu một đối tượng thực hiện một số hoạt động trên đối tượng kia? (Điều này được gọi là Nguyên tắc The Common Reuse Principle – Classes, được sử dụng cùng nhau được đóng gói cùng nhau của Robert C. Martin trong bài báo “Granularity” năm 1996, 4 năm sau cuốn sách Ivar Jacobson)
Một tiêu chí khác cho việc phân chia là phải có ít thông tin trao đổi giữa các hệ thống con khác nhau càng tốt (low coupling)
Đối với các dự án lớn, có thể có các tiêu chí khác cho phân hệ thống con, ví dụ:
Các nhóm phát triển khác nhau có năng lực hoặc nguồn lực khác nhau và có thể phân phối các công việc phát triển phù hợp (các nhóm cũng có thể được tách biệt về mặt địa lý)
Trong một môi trường phân tán, một hệ thống phụ có thể được yêu cầu ở mỗi logical node (SOA, web services và micro services) Nếu một sản phẩm hiện có có thể được sử dụng trong hệ thống này, điều này có thể được coi là một subsystem (các libraries mà hệ thống phụ thuộc vào, ví dụ như ORM).
ANTI-CORRUPTION LAYER
Một Anti-Corruption Layer cơ bản là một middleware giữa hai hệ thống con. Nó được sử dụng để cô lập hai hệ thống con, làm cho chúng phụ thuộc vào layer này thay vì phụ thuộc trực tiếp vào nhau. Bằng cách này, nếu chúng ta tái cấu trúc hoặc thay thế hoàn toàn một trong các hệ thống con thì chúng ta sẽ chỉ phải cập nhật layer này để các hệ thống con khác không bị ảnh hưởng.
Điều này đặc biệt hữu ích khi có một hệ thống mới mà chúng ta cần phải tích hợp với một hệ thống có sẵn. Để không để những hệ thống cũ chịu sự ảnh hưởng từ việc thêm mới các hệ thống con mới, chúng ta tạo ra một Anti-Corruption Layer sẽ điều chỉnh API của hệ thống cũ cho các nhu cầu của hệ thống con mới.
Có 3 mối quan tâm chính:
Điều chỉnh các API hệ thống con với những gì các client subsystems cần;
Translate data và commands giữa các hệ thống con;
Thiết lập trao đổi (communication) theo một hoặc nhiều hướng, nếu cần
Eric Evans, 2003
Đây là một kỹ thuật được sử dụng hợp lý khi chúng ta không kiểm soát một hoặc tất cả các hệ thống con, nhưng cũng có thể sử dụng nó khi chúng ta kiểm soát tất cả các hệ thống con liên quan, ngay cả khi chúng được thiết kế tốt nhưng đơn giản có các model rất khác nhau và chúng ta muốn ngăn chặn sự rò rỉ từ model này sang model khác (thay đổi một hệ thống con để phù hợp với nhu cầu của một hệ thống con khác).
SHARED KERNEL
Trong một số trường hợp, bất chấp mong muốn của chúng ta để có các thành phần tách biệt hoàn toàn và tách rời, vẫn có một số trường hợp buộc ta phải tách một số domain code ra để chia sẻ cho nhiều component khác sử dụng.
Điều này sẽ cho phép các component vẫn giữ được tính phân tách và độc lập với các component khác mặc dù sử dụng chung những mã chia sẻ cùng (shared code), ta gọi các mã chia sẻ này với cái tên “shared kernel”.
Trường hợp ví dụ, với các events được kích hoạt bởi một component và lắng nghe bởi một hoặc một số component khác. Và tương tự cho các service interfaces and thậm chí là các entities.
Tuy nhiên, nên giữ phần Shared Kernel này càng nhỏ càng tốt, và cẩn thận khi thay đổi nó vì chúng ta có thể một cách vô tình gây ảnh hưởng đến những chỗ khác đang sử dụng nó. Điều quan trọng là mã trong Shared Kernel sẽ không nên bị thay đổi nếu không có sự tham gia và hiểu biết của tất cả các nhóm phát triển khác sử dụng nó.
GENERIC SUBDOMAIN
Một Subdomain là một phần rất biệt lập của domain. Generic Subdomain là một Subdomain không liên quan đến ứng dụng của chúng ta mà có thể được sử dụng trong bất kỳ ứng dụng nào tương tự.
Vì vậy, nếu có một ứng dụng có một phần của nó là về finance, có lẽ chúng ta có thể sử dụng một thư viện finance hiện có trong ứng dụng. Nhưng dù sao đi nữa, ngay cả khi không thể sử dụng thư viện hiện có và cần xây dựng riêng của chúng ta, nếu nó là một Generic Subdomain thì đó không phải là hoạt động cốt lõi và nó cần phải được coi là cần thiết nhưng không quan trọng. Đây không phải là phần quan trọng nhất trong ứng dụng nên không phải là nơi các chuyên gia giỏi nhất nên tập trung và thậm chí phải rõ ràng bên ngoài mã nguồn chính, nó có thể được cài đặt với một công cụ quản lý sự phụ thuộc (dependency management tool).
KẾT LUẬN
Các khái niệm DDD tôi đã chọn để tiếp cận ở đây là, một lần nữa, chủ yếu về single responsibility, low coupling, high cohesion, isolating logic để ứng dụng của chúng ta trở nên nhất quán, dễ dàng và nhanh chóng hơn để thay đổi và thích ứng với nhu cầu của doanh nghiệp.
Đây là bài viết trong loạt bài viết về “Tổng quan về sự phát triển của kiến trúc phần mềm“. Đây là loạt bài viết chủ yếu giới thiệu về một số mô hình kiến trúc phần mềm hay nói đúng hơn là sự phát triển của chúng qua từng giai đoạn, qua đó giúp chúng ta có cái nhìn tổng quát, up-to-date và là roadmap để bắt đầu hành trình chinh phục (đào sâu) thế giới của những bản thiết kế với vai trò là những kỹ sư và kiến trúc sư phần mềm đam mê với nghề.
Với mỗi sinh viên IT, việc đưa ra quyết đưa ra quyết định học lập trình web ở đâu là một lựa chọn ảnh hưởng lớn tới tương lai sau này. Tại các trường đại học ở Việt Nam, lập trình web thường chỉ dừng ở mức cơ bản, đủ để sinh viên nắm bắt được lý thuyết chứ chưa thực sự làm chủ được các ngôn ngữ lập trình, chưa được trực tiếp làm các công việc thực tế. Cho nên việc lựa chọn giữa tự học hay đi học ở các trung tâm làm cho các bạn sinh viên hết sức băn khoăn. Đây cũng là câu hỏi thường gặp ở nhiều diễn đàn IT và bây giờ, chúng ta hãy cùng đi tìm lời giải cho bài toán này.
Có rất nhiều ý kiến được đưa ra:
Nên đi học ở trung tâm
Nếu bạn chưa quen với việc lập trình thì mình khuyên bạn nên tìm một trung tâm uy tín để học. Dưới đây là một số lý do bạn cần đến trung tâm để học:
Thứ nhất: Học ở trung tâm bạn sẽ được dạy theo một bộ giáo trình nhất định từ cơ bản đến nâng cao. Khi đó bạn sẽ có được những kiến thức cơ bản nhất và tránh được việc bị hổng kiến thức.
Thứ hai: Bạn sẽ có một môi trường làm việc nhóm nơi bạn có thể trao đổi thông tin và rèn luyện kỹ năng một cách tốt nhất. Bạn sẽ không mất nhiều công sức để tìm lời giải thích cho một lỗi sai nào đó hay để tìm tài liệu cho những vấn đề bạn quan tâm.
Thứ ba: Bạn sẽ được làm việc với những người có nhiều kinh nghiệm và được chia sẻ nhiều kiến thức thực tế bổ ích có liên quan trực tiếp tới công việc của bạn sau này.
Thứ tư: Nhiều trung tâm sẽ cấp chứng chỉ sau các khóa học, điều này sẽ góp phần làm đẹp thêm cho bộ hồ sơ xin việc của bạn sau này.
Sau khi có đầy đủ kiến thức về lập trình, các bạn có thể đọc thêm các Ebook hay xem các video trên mạng, tham gia các nhóm lập trình trên Facebook. Bạn hoàn toàn có thể tạo một trang web riêng và code từ một trình soạn thảo, như vậy kỹ năng của bạn sẽ được cải thiện rất nhiều.
Khi bạn đã biết lập trình web cơ bản, bạn làm chủ được kiến thức của mình và đã có một ngôn ngữ lập trình riêng để theo đuổi thì cũng không cần thiết phải tốn tiền vào các trung tâm. Điều quan trọng là bạn cần có khả năng tự học, tự mày mò hoặc đã có chỗ để thực tập trong thời gian còn ngồi trên ghế nhà trường. Một kế hoạch cụ thể sữ giúp cho bạn có được hiệu quả tốt nhất trong việc học.
Đầu tiên bạn cần xác định loại ngôn ngữ bạn sẽ học. Theo mình, nên bắt đầu từ ngôn ngữ R hay Python bởi nó sẽ giúp ích cho ngành học của bạn hơn. Còn nếu bạn muốn làm được nhiều việc thì nên chọn C#. Tiếp đến là Java, PHP hay Ruby tùy theo sở thích của bạn. Sau khi có được kiến thức lập trình cơ bản, bạn cần dành nhiều thời gian cho việc thực hành để tránh các lỗi và để nắm vững ngôn ngữ đó.
Một việc nữa các bạn cần lưu ý khi tự học là cân đối giữa việc học ở trường và việc tự học của bạn. Cần xem trước kế hoạch học ở trường (bạn đang học ngôn ngữ nào, bạn sắp học ngôn ngữ nào,…) để có sự chuẩn bị tốt nhất cho việc tự học. Bên cạnh đó, nếu bạn có một người nhiều kinh nghiệm hướng dẫn là tốt nhất. Đôi khi chúng ta không chạy được chương trình và không biết lỗi ở đâu nên rất cần một người có kinh nghiệm để thường xuyên trao đổi.
Khi bạn đã thành thạo một ngôn ngữ, bạn có thể làm một số công việc thực tế để tích lũy kinh nghiệm đồng thời tìm hiểu sâu hơn về ngôn ngữ đó. Nếu bạn làm tốt thì chỉ cần 2 đến 5 tháng là sử dụng nhuần nhuyễn một ngôn ngữ. Sau đó, bạn có thể chuyển sang một ngôn ngữ mới nhưng đừng quên thường xuyên ôn lại những kiến thức và kỹ năng đã học nếu không bạn sẽ rất chóng quên.
Học theo cách này rất tốn thời gian, không dành cho những người dễ nản chí. Bạn có thể lên rất nhiều kế hoạch nhưng lại không thực hiện được bởi nhiều lý do cho nên hãy cân nhắc kỹ trước khi lựa chọn phương án tự học.
Tự học online
Học lập trình online cũng có rất nhiều chuyên gia truyền đạt lại các kinh nghiệm thực tế. Đây là cách bạn có thể lựa chọn để tiết kiệm cả thời gian và chi phí so với hai cách nêu trên. Các kênh mà bạn có thể lựa chọn là học qua Skype, học qua facebook (những người chuyên viết blog về lập trình, học qua các nhóm,…), học lập trình web từ các diễn đàn,… Ngoài ra bạn có thể đăng ký các khóa học trực tuyến qua các trang imicrosoft.edu.vn; standford.com.vn; itech.edu.vn;…
Dù học theo cách nào thì tự học và tự thực hành là những kỹ năng cần thiết nhất đối với một lập trình viên. Và thêm một lời khuyên cho các bạn sinh viên là nên đi làm thêm vào năm 2 hoặc năm 3 là tốt nhất. Nếu đã có kinh nghiệm, rất dễ để các bạn có được một vị trí “ngon lành” khi mới ra trường.
Các thuật ngữ như Internet of Things hay M2M có lẽ không quá xa lạ với dân IT. Có rất nhiều cách định nghĩa về IoT và trên thực tế đây là một cụm từ khá trừu tượng nên không ít người không biết IoT hoạt động thế nào. Chúng ta hãy cùng đi tìm lời giải đáp.
MVC được hình thành bởi các nghiên cứu của Trygve Reenskaug vào khoảng các năm 1978-1979. Sau đó nó được điều chỉnh và được cài đặt lần đầu tiên vào các lớp của thư viện Xerox PARC Smalltalk-80. Mô hình MVC cổ điển hiện tại ít được sử dụng trong môi trường lập trình desktop như trước đây nhưng hiện tại nó vẫn được sử dụng cực kì rộng rãi như là kiến trúc cơ bản trong các môi trường lập trình web.
Tổng quan mô hình MVC
Tổng quan mô hình MVC
MVC là gì?
Mô hình MVC – Model-View-Controller là phương pháp chia nhỏ các các thành phần dữ liệu (data), trình bày (output) và dữ liệu nhập từ người dùng (input) thành những thành phần riêng biệt.
MVC hoạt động như thế nào?
Thông thường, chúng ta biết rằng mô hình MVC gồm 3 thành phần: Model, View và Controller
View – Nơi người dùng tương tác.
Controller – Xử lý yêu cầu và gửi phản hồi đến view.
Model – Middleware xử lý các thao tác cơ sở dữ liệu.
Mô hình MVC hoạt động như thế nào?
View
Về cơ bản, View đại diện cho cách dữ liệu được trình bày trong ứng dụng (UI). Các view được tạo ra dựa trên dữ liệu thu thập từ model. Bằng cách yêu cầu thông tin từ model, sau đó sẽ trả kết quả tới người dùng. Ngoài việc hiển thị dữ liệu từ các biểu đồ, sơ đồ và bảng, view còn hiển thị dữ liệu từ các nguồn khác. Tất cả các thành phần giao diện người dùng, chẳng hạn như hộp văn bản, menu thả xuống, v.v., sẽ xuất hiện trong bất kỳ view nào của khách hàng.
Controller
Controller là thành phần xử lý tương tác của người dùng. Dữ liệu đầu vào của người dùng được controller phân tích và xử lí, khi người dùng thao tác bất kì với hệ thống controller sẽ gửi thông tin đến model để xử lí và sau đó trả về kết quả view
Người dùng -tương tác-> Controller => Model => View (output) -trả kết quả-> Người dùng
Bằng cách giao tiếp với view liên quan của controller, người dùng có thể thay đổi giao diện của view (ví dụ: cuộn qua một tài liệu) và cập nhật trạng thái của model liên quan (ví dụ: lưu một tài liệu).
Model
Model là nơi lưu trữ dữ liệu và logic. Ví dụ, khi Controller truy xuất thông tin khách hàng từ cơ sở dữ liệu, dữ liệu được chuyển đổi giữa các thành phần controller hoặc giữa các yếu tố logic nghiệp vụ. Nó thao tác dữ liệu và gửi lại cơ sở dữ liệu, hoặc được sử dụng để hiển thị thông tin tương tự.
Ngoài ra, nó phản hồi các yêu cầu từ view và có các chỉ thị từ controller cho phép nó tự cập nhật. Nó cũng là mức thấp nhất của mô hình chịu trách nhiệm duy trì dữ liệu.
Ứng tuyển ngay các vị trí PHP tuyển dụng mới nhất trên TopDev
Ví dụ thực tiễn về mô hình MVC
Khi bạn đến quán trà đá và gọi 1 cốc trà đá. Lúc này:
Bạn là “người dùng” và “cốc trà đá” là “yêu cầu từ phía người dùng”.
Đối với bà chủ quán, cốc trà đá là một quy trình gồm các bước:
Lấy cái cốc
Cho đá vào
Cho trà vào
Cho thêm nước lọc cho trà loãng bớt
Khuấy đều lên
Đưa cốc trà cho bạn
Thanh toán
Bộ não của bà chủ quán lúc này đóng vai trò Controller. Kể từ thời điểm bạn nói “một cốc trà đá” bằng tiếng Việt và bà chủ quán hiểu được, công việc bắt đầu. Trà đá, nước mía hay cocktail thì cũng như nhau, nhưng nguyên liệu thì hoàn toàn khác biệt. Bà chủ quán chỉ có thể sử dụng những công cụ và nguyên liệu của quán, và những công cụ đó sẽ đóng vai trò Model, bao gồm:
Đôi tay của bà chủ
Các nguyên liệu pha chế (trà, nước …)
Đá lạnh
Bia, nước ngọt, thuốc lá…
Chanh, sấu, gừng…
Các ly cốc để đựng đồ uống
Những nguyên liệu và công cụ này, thông qua một loạt các bước, đã trở thành cốc trà đá mát lạnh đến tay bạn. Cốc trà đá lúc này đóng vai trò View. “View” được làm nên từ những công cụ, nguyên liệu trong “Model”, được chế biến và bàn giao tới tay bạn thông qua “Controller” (chính là bộ não của bà chủ quán).
Mô hình MVC ra đời giúp các lập trình viên giải quyết nhiều vấn đề lúc bấy giờ, cùng điểm qua các ưu điểm của MVC:
Mã nguồn dễ bảo trì và mở rộng: Kiến trúc MVC giúp mã nguồn dễ bảo trì, có thể mở rộng và phát triển một cách dễ dàng.
Các thành phần có thể kiểm tra độc lập: Các thành phần của nó có thể được kiểm tra riêng biệt từ các thành phần người dùng.
Hỗ trợ các loại khách hàng mới dễ dàng hơn: Kiến trúc này hỗ trợ việc thêm các loại khách hàng mới một cách dễ dàng.
Phát triển song song các thành phần: Có thể phân chia phát triển các thành phần khác nhau một cách song song.
Giảm bớt độ phức tạp: Bằng cách chia ứng dụng thành ba phần, bạn có thể tránh được sự phức tạp.
Sử dụng mô hình Front Controller: Chỉ sử dụng mô hình Front Controller, trong đó mỗi yêu cầu được xử lý bởi một bộ điều khiển duy nhất.
Hỗ trợ phát triển theo hướng kiểm thử tối đa: Hỗ trợ phát triển theo hướng kiểm thử (TDD) một cách tối đa.
Dễ dàng cho các nhóm phát triển lớn: Một nhóm lớn các nhà thiết kế và phát triển web có thể tạo và duy trì các ứng dụng web với nó.
Kiểm tra từng lớp và đối tượng riêng biệt: Bạn có thể kiểm tra tất cả các lớp và đối tượng riêng lẻ vì chúng đều độc lập với nhau.
Hành động của bộ điều khiển có thể nhóm logic: Các hành động của bộ điều khiển có thể được nhóm lại một cách logic bằng cách sử dụng các mẫu thiết kế MVC.
Nhược điểm của Kiến trúc MVC
Bên cạnh ưu điểm MVC cũng tồn tại một số nhược điểm:
Khó đọc, thay đổi và kiểm thử đơn vị: Khó đọc, thay đổi và kiểm thử đơn vị mô hình này vì không có thành phần riêng biệt để xử lý giao diện người dùng (UI). Tất cả phải được thực hiện trên lớp view. Vì vậy, cần phải phụ thuộc vào một framework khác để làm điều đó.
Không hỗ trợ xác thực chính thức: Kiến trúc MVC không cung cấp hỗ trợ xác thực chính thức. Vì vậy, việc xác thực cần phải được thực hiện rõ ràng.
Xử lý dữ liệu có thể không hiệu quả: Có thể dẫn đến quá trình xử lý dữ liệu không hiệu quả vì nó làm cho logic thực thi trở nên phức tạp.
Khó sử dụng với giao diện người dùng hiện nay: Việc sử dụng MVC khó khăn với giao diện người dùng hiện đại. Hầu hết các framework UI phổ biến hiện nay đều có kiến trúc triển khai riêng của chúng và không thể nhúng vào MVC.
Cần duy trì nhiều mã trong bộ điều khiển: Cần duy trì nhiều mã trong các bộ điều khiển, gần như cho mỗi hành động khác nhau trên trang, chúng ta cần khai báo các phương thức Action riêng biệt.
Nhầm lẫn về MVC
Một nhầm lẫn thường gặp trong quan hệ giữa các thành phần MVC là khi xem mục đích của Controller như là thành phần trung gian để tách rời View khỏi Model. Trong khi thực tế, kiến trúc MVC tách rời dữ liệu và xử lý trung tâm khỏi phần trình bày thông qua cơ chế là Observer Pattern chứ không phải Controller. Nhiệm vụ của Controller là cần nối giữa người dùng là ứng dụng, không phải giữa View và Model.
Trong khi mục đích chính của MVC là tách rời trình bày và các xử lý bên trong. Việc phân rõ vai trò xử lý ouput (View) và input (Controller) là một hệ quả nhằm hoàn thiện cơ chế cho ý tưởng trên. Hiện nay trong nhiều môi trường lập trình hiện đại, nhiều control được cung cấp và hoàn thiện hơn (nhiều xử lý sự kiện cơ bản đã được hỗ trợ sẵn) so với trước đây nên việc khoáng tất cả các xử lý sự kiện cho một thành phần độc lập như Controller không còn là vấn đề quan trọng nữa.
Trong khi đó, những cơ chế như Observer Pattern cũng có vấn đề của riêng chúng. Trong khi được dùng như phương tiện hiệu quả để loại bỏ sự phụ thuộc của Model vào các thành phần khác, nó có một vấn đề lớn là tại một thời điểm, chúng ta khó có thể xác định điều gì sẽ xảy ra bằng cách đọc code và việc thực hiện các testing cũng khó khăn hơn. Hơn nữa, do Model chỉ liên kết gián tiếp đến View thông qua Observer Pattern, khi sự thay đổi trạng thái của Model cần đến một vài thao tác xử lý phức tạp để áp dụng lên giao diện thì với mô hình cổ điển sẽ gặp khó khăn.
Một vấn đề khác là chúng ta cần lưu trữ tình trạng hiện tại của UI (UI state), ví dụ trong danh sách sinh viên thì chúng ta cần biết sinh viên nào đang được chọn. Trong khi thành phần UI nắm giữ dữ liệu trình bày đang được chọn thì dữ liệu sinh viên thuộc về Model, như vậy dữ liệu về sinh viên được chọn sẽ được lưu trữ ở đâu khi cần truy xuất đến?
Vì những lí do trên, MVC sau này đã có những thay đổi và bổ sung nhất định (như khái niệm Application Model). Kiến trúc MVP chúng ta sẽ bàn dưới đây cũng dựa trên tư tưởng cơ bản của MVC nhưng với cách tiếp cận khác nhằm mục đích khắc phục các khuyết điểm đã có.
Bài viết được sự cho phép của tác giả Kien Dang Chung
Video trong bài viết
Ứng dụng Todo List đã gần thành hình với các chức năng tạo bản ghi mới, xem danh sách bản ghi và xem chi tiết từng bản ghi. Tiếp theo, trong bài học hôm nay chúng ta cùng tìm hiểu về một công việc rất quan trọng: Kiểm tra dữ liệu. Tại sao kiểm tra dữ liệu quan trọng? chúng ta cùng tìm hiểu nhé.
Người dùng không hề biết phải nhập dữ liệu như thế nào vào ứng dụng, đặc biệt khi mới lần đầu sử dụng và như vậy việc nhập liệu có thể dẫn đến lỗi ứng dụng. Hơn nữa, dữ liệu là một tài nguyên quan trọng trong ứng dụng, muốn khai thác tài nguyên này chúng ta cần có tài nguyên được sắp xếp và phân loại một cách rõ ràng. Ví dụ như một ô nhập liệu về ngày sinh, có rất nhiều các giá trị như 01/02/1983, 19830201, Feb 01 1983, Ngày 01 tháng 02 năm 1983… tuy nhiên, máy tính lại không thể hiểu tất cả các kiểu nhập liệu này, đặc biệt khi khai thác dữ liệu chúng ta rất dễ bị nhầm lẫn, vậy nên việc kiểm soát dữ liệu và bắt người dùng thực hiện các quy tắc nhập liệu ngay từ đầu là một việc rất quan trọng.
Các controller trong Laravel đều được kế thừa từ class App\Http\Controllers\Controller, mà class này sử dụng trait ValidateRequests cho phép chúng ta kiểm tra dữ liệu thông qua gọi phương thức validate().
Trở lại đoạn code lưu dữ liệu xuống database trong bài trước, chúng ta cần kiểm tra dữ liệu trước khi thực hiện lưu dữ liệu, cùng xem đoạn code thực hiện như sau:
Tham số thứ nhất là đối tượng request chứa thông tin về dữ liệu được gửi lên từ người dùng.
Tham số thứ hai là một mảng các quy tắc kiểm tra cho từng trường nhập liệu có trong request.
Trường name: bắt buộc nhập, tối thiểu 6 ký tự, tối đa 12 ký tự.
Trường description: bắt buộc nhập.
Như vậy chúng ta đã thực hiện kiểm tra dữ liệu trước khi lưu trữ xuống database. Tuy nhiên nếu chúng ta thực hiện nhập liệu sai thì không thấy ứng dụng có phản hồi gì cả, đó là do chúng ta chưa hiển thị thông báo lỗi nhập liệu ra ứng dụng.
Hiển thị thông báo lỗi kiểm tra dữ liệu
Mặc định trong Laravel, khi kiểm tra dữ liệu gặp lỗi, hệ thống tự động truyền đến trang (view) hiện tại một biến là $errors. Biến này chứa thông tin về các lỗi xảy ra khi kiểm tra dữ liệu.
Trong view hiện hành, ở đây là create.blade.php, để hiển thị các lỗi kiểm tra dữ liệu nếu có, chúng ta sử dụng một vòng lặp và hiển thị các lỗi là một thành phần của danh sách:
Bài viết được sự cho phép của blogchiasekienthuc.com
Chào các bạn, một vài hôm trước mình có đọc được một bài báo thống kê rằng năm học 2021 ngành IT nói riêng và khối ngành công nghệ kỹ thuật nói chung là một trong những ngành có tỷ lệ chọi cao nhất (khoảng 1/64).
Nói đến đây đủ để thấy rằng trong những năm trở lại đây thì ngành công nghệ thông tin đã trở nên “hot” như thế nào!
Một câu hỏi đặt ra là liệu với số lượng lớn học sinh có ý định theo học ngành IT như vậy thì trong một vài năm tới, ngành IT có còn “hot” như vậy được nữa hay không? Liệu nhân lực ngành này có bị bão hòa hay không?
Trong bài viết này mình sẽ chia sẻ một vài quan điểm của cá nhân mình dưới cái nhìn của một người đang học và làm về IT về hai câu hỏi trên.
#1. Nhiều người đang “ảo tưởng” về ngành IT
Có lẽ những câu chuyện về sinh viên IT mới ra trường làm lương 2000 – 3000$ một tháng, hay những bài báo giật tít về mức thu nhập “khủng” của dân IT đã khiến nhiều người ảo tưởng về ngành này.
Điều này cũng dễ hiểu thôi vì người dân Việt Nam mình thường có xu hướng làm theo đám đông. Nhiều người không chịu bỏ thời gian tìm hiểu gốc rễ vấn đề mà luôn tin vào hiệu ứng đám đông, ủng hộ số đông. Sợ thật ◔◡◔
Là một người học và làm IT thì mình hiểu rất rõ về vấn đề thu nhập, để đạt được mức lương ngàn đô hay mấy chục triệu một tháng khi mới ra trường (như lời đồn) là điều rất khó, thực sự khó.
Trừ khi bạn là người có năng lực thực sự, kiểu mấy ngàn người mới có một người ấy. Mà các bạn biết đấy, con số này rất ít.
Và mình tin là có rất nhiều bạn học sinh khi đăng ký học công nghệ thông tin thì ít nhiều đã bị tác động bởi những con số có chút “ảo” này, mà không chịu tìm hiểu kỹ càng.
Bạn nên nhớ là, bạn nên theo đuổi những cái mà bạn thực sự thích và muốn tìm hiểu. Giỏi thì nghề nào cũng giàu thôi. Và có như vậy mới bền lâu được !
Nhưng cũng chẳng thể trách được, vì công tác hướng nghiệp của Việt Nam chúng ta còn quá yếu kém, trong khi báo chí thì lại thường xuyên thổi phồng dẫn đến nhiều bạn học sinh bị “ảo tưởng” và hệ lụy là tỷ lệ chọi cao ngất ngưởng.
Quay lại với câu hỏi thì “ảo tưởng” như thế thì có ảnh hưởng gì đến độ “hot” của ngành này trong vài năm tới hay không?
Các bạn cứ hình dung thử xem, bạn bị lừa thì cùng lắm là chỉ bị lừa một lần thôi chớ. Ví dụ như trong nhà bạn có ông anh làm IT lương tháng cũng 9 – 10 triệu, trong khi đó phải làm sờ mờ lờ (sấp mặt luôn) suốt ngày…
Thử hỏi nếu bạn định đăng ký học IT thì ông anh bạn có nói như báo đài nói hay không? Có thể ông ý vẫn bảo bạn thích thì học, lương cũng không tệ nhưng chắc chắn là bạn sẽ phải suy nghĩ lại một cách thấu đáo hơn.
Số lượng và chất lượng là những con số thường tỷ lệ nghịch đối với lao động Việt Nam.
Mình không hề có ý chê bai chất lượng lao động của người Việt Nam thấp, nhưng thực tế cho thấy, với các ngành đòi hỏi phải làm việc trí óc nhiều như làm IT thì hiệu suất làm việc của chúng ta rất thấp, đây là một sự thật mà chúng ta cần phải nhìn nhận để cố gắng hơn.
Khi mà số lượng rất lớn người đổ xô đi học công nghệ thông tin nhưng chất lượng đào tạo lại chưa được tốt, đào tạo ra nhưng không làm được việc, vẫn nặng về lý thuyết, thiếu thực hành, thiếu tính thực tế…
Mà các bạn biết đó, bất cứ thị trường nào cũng có tính đào thải, đặc biệt là những thị trường lao động đòi hỏi trí óc. Mà với dân IT, 90% kiến thức là tự học, công nghệ thay đổi theo từng giờ..
Nhà tuyển dụng họ sẵn sàng loại đi 9 trong 10 người, chỉ để lấy một người có năng lực thực sự, phù hợp và đáp ứng được công việc mà họ cần.
Điều này đồng nghĩa với việc nhiều người nghĩ cứ học công nghệ thông tin ra trường kiểu gì cũng có việc là hoàn toàn sai lầm. Việc thì có đấy, nhưng quan trọng bạn kiếm được bao nhiêu tiền..
Bạn phải hiểu rằng, số lượng càng nhiều thì mức độ cạnh tranh càng khốc liệt, mà cạnh tranh càng khốc liệt thì mức độ đào thải càng cao.
Và đến một thời điểm, mức độ đào thải đủ để cân bằng cung và cầu về nhân lực ngành IT thì lúc đó ngành IT sẽ không còn “hot” như hiện tại nữa.
#3. Sự phát triển của nhiều ngành nghề mới
Nếu bạn để ý thì có thể thấy ngành IT bây giờ cũng giống như ngành kế toán ngày trước. Từng có thời kỳ rất nhiều người đổ xô đi học kế toán, ngân hàng… các thứ !
Ngành IT nói riêng và các khối ngành kỹ thuật nói chung chịu ảnh hưởng tích cực từ cuộc cách mạng 4.0 nên nhu cầu nhân lực chất lượng đang rất hiếm.
Nhưng rõ ràng, cuộc cách mạng 4.0 không chỉ ảnh hưởng đến lĩnh vực công nghệ không đâu, mà nó còn tác động rất nhiều đến các ngành nghề khác nữa.
Nhiều ngành nghề phát triển rất nhanh nhờ áp dụng chính thành quả của các sáng tạo công nghệ. Ví dụ như bán hàng online, Maketing online, nuôi trồng áp dụng công nghệ cao…
Bất cứ ngành nghề nào cũng có thể áp dụng các tiến bộ khoa học kỹ thuật được. Nhưng điều đó không có nghĩa là những ngành nghề đó phụ thuộc vào công nghệ.
Công nghệ mở ra một hướng đi mới để từ đó người ta phát triển ngành đó theo một hướng đi mới. Tốt hơn và hiệu quả hơn !
Và tất nhiên, như một điều tất yếu thì người lao động sẽ có thêm những lựa chọn mới, những hướng đi mới cho những gì họ vẫn đang làm.
Cá nhân mình thấy thì đây chính là nguyên nhân có tác động mạnh mẽ nhất đến mức độ “hot” của ngành IT trong vài năm tới, vì theo thống kê có một số lượng lớn người học IT sau khi học xong ra trường lại không làm IT.
Họ chuyển hướng sang làm những công việc không liên quan trực tiếp đến công nghệ, hay nói cách khác là họ chuyển hướng sang làm các công việc có ứng dụng công nghệ. Hai cái này khác nhau nhé, các bạn đừng nhầm lẫn !
#4. Lời kết
Tóm lại, theo nhận định của cá nhân mình thì trong một vài năm tới, ngành IT vẫn sẽ rất “hot” bởi vì thị trường lao động này chưa đạt đến độ bão hòa về số lượng, trong khi chất lượng chưa thay đổi nhiều.
Nhưng sau một vài năm nữa mình tin chắc mức độ “hot” sẽ giảm dần do có nhiều ngành nghề mới ra đời.
Và thực tế đã co thấy, làm việc trong ngành IT không phải “ngồi mát ăn bát vàng” như nhiều người vẫn nghĩ. Đến một lúc nào đó, nhiều người nhận ra được sự thật này thì họ sẽ tự động thay đổi quan điểm và ngành IT sẽ hết “hot” mà thôi.
Mình chỉ có một lời nhắn nhủ chân thành như thếnày: Nếu các bạn thực sự đam mê với ngành IT, một lĩnh vực nào đó trong ngành IT thì wellcome, bạn nên tham gia ngay. Còn nếu bạn chỉ học IT vì bạn đọc đâu đó, hoặc nghe đâu đó vì có lương cao thì nên cân nhắc lại.
Vâng, đó là những quan điểm của cá nhân mình, không biết các bạn nghĩ thế nào. Nếu có quan điểm gì khác thì hãy comment bên dưới nha. Xin chào và hẹn gặp lại các bạn trong các bài viết tiếp theo.
Trong các bài viết trước, chúng ta đã cùng tìm hiểu về Direct Exchange. Trong bài này, tôi sẽ giới thiệu với các bạn một loại exchange khác là Fanout Exchange.
Fanout exchange (định tuyến broadcast – amq.fanout) định tuyến message (copy message) tới tất cả queue mà nó được bind, với bất kể một routing key nào. Giả sử, nếu nó N queue được bind bởi một Fanout exchange, khi một message mới published, exchange sẽ định tuyến message đó tới tất cả N queues. Fanout exchange được sử dụng cho định tuyến message broadcast (quảng bá).
Flow của một Message trong Fanout Exchange như sau:
Một Producer sẽ tạo một Message và publish tới Exchange.
Một hoặc nhiều Queue bind tới Fanout Exchange không cần thông tin routing key.
Một Message tới Exchange sẽ được chuyển tiếp đến tất cả các Queue mà không có bất kỳ điều kiện kiểm tra nào.
Exchange Fanout hữu ích với trường hợp ta cần một dữ liệu được gửi tới nhiều ứng dụng khác nhau với cùng một message nhưng cách xử lý ở mỗi ứng dụng là khác nhau.
Ví dụ Fanout Exchange trong RabbitMQ
Trong ví dụ này, tôi tạo một Fanout Exchange có tên GPCoderFanoutExchange, tạo 3 Queue binding tới Fanout Exchange này: QDeveloper, QManager, QGeneral.
Một số class của chương trình:
ConnectionManager : hỗ trợ tạo Connection đến RabbitMQ.
FanoutExchangeChannel : class util hỗ trợ tạo Echange, Queue, binding Queue đến Exchange, publish/ subscribe message, …
Constant : định nghĩa constant chứa các thông tin về tên Exchange, Queue.
Producer: để gửi Message đến Exchange.
Consumer: để nhận Message từ Queue.
App: giả lập việc gửi nhận Message thông qua Fanout Exchange của RabbitMQ.
ConnectionManager.java
package com.gpcoder.fanoutexchange;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConnectionManager {
private ConnectionManager() {
super();
}
public static Connection createConnection() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
return factory.newConnection();
}
}
package com.gpcoder.fanoutexchange;
public final class Constant {
// Exchange
public static final String EXCHANGE_NAME = "GPCoderFanoutExchange";
// Queue
public static final String DEV_QUEUE_NAME = "QDeveloper";
public static final String MANAGER_QUEUE_NAME = "QManager";
public static final String GENERAL_QUEUE_NAME = "QGeneral";
private Constant() {
super();
}
}
package com.gpcoder.fanoutexchange;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class App {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
// Create producer
Producer producer = new Producer();
producer.start();
// Send one message to exchange, it will be forwarded to all queues
producer.send("gpcoder message 1");
// Create consumer
Consumer consumer = new Consumer();
consumer.start();
consumer.subscribe();
TimeUnit.SECONDS.sleep(1);
// Try to send a second message
producer.send("gpcoder message 2");
}
}
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Trong OAuth 2.0, chúng ta có thể có nhiều loại Client Application khác nhau mà người dùng có thể sử dụng để access tới các resources của resource server. Ví dụ như chúng ta có native mobile application, web application bao gồm cả Single Page Application, console hay backend application, … Những Client Application này sẽ cần phải đăng ký với Authorization Server và sử dụng thông tin Client ID được cung cấp bởi Authorization Server để lấy access token. Một số grant type trong OAuth 2.0 đòi hỏi chúng ta phải cung cấp cả Client Secret, cái mà Client Application được Authorization Server cung cấp cùng với Client Id, ví dụ như grant type Client Credentials chẳng hạn.
Không phải tất cả các Client Application đều có thể lưu trữ Client Secret một cách bảo mật. Ví dụ như Native mobile application hay Single Page Application. Vì thế, OAuth 2.0 định nghĩa 2 loại Client Types khác nhau bao gồm: các confidential clients và các public clients.
Confidentials clients là những client có thể lưu trữ Client Secret bảo mật, ví dụ như chúng ta có những web application có cả backend và frontend thì Client Secret có thể lưu trữ ở backend side, không ai có thể lấy được thông tin này.
Ngược lại thì public clients là những client không thể đảm bảo việc lưu trữ Client Secret bảo mật, ví dụ như native mobile application hay Single Page Application, người dùng có thể decode hoặc view source code để xem thông tin Client Secret. Đối với những clients này, chúng ta cần sử dụng những grant type mà không cần Client Seret ví dụ như Authorization Code grant type với PKCE các bạn nhé!
Snowpack là một công cụ xây dựng để xây dựng môi trường phát triển front-end.
Snowpack cung cấp một bộ khởi động độc lập cho mỗi môi trường phát triển được gọi là Tạo ứng dụng Snowpack (CSA). Lần này, tôi sẽ giới thiệu quy trình tạo một Thành phần Web đơn giản bằng cách sử dụng app-template-lit-element là một trong Tạo ứng dụng Snowpack .
Decorators chưa có sẵn trong JavaScript gốc, nhưng chúng có thể được sử dụng với các plugin của Babel
Bên cạnh việc xác định custom element, hãy xác định mẫu Shadow DOM cho component. Hãy render()triển khai một hàm của lớp LitElement . Call the lit-element htmlfunction in a tagged template literal so that the render()function returns the result.
Khi mô tả được hoàn thành cho đến nay, các phần tử của màn hình được hiển thị ./src/app-root.jsvà thành phần đã tạo được importđọc bởi một câu lệnh. Sau đó, ./src/app-root.jscác render()chỉ định nghĩa các chức năng <toggle-button>để mô tả.
Nếu bạn thực thi mã cho đến nay trong trình duyệt, nó sẽ giống như hình chụp sau.
Property
Tôi muốn chuyển đổi kiểu nút và văn bản được kích hoạt bởi sự kiện nhấp chuột, vì vậy tôi muốn xác định thuộc tính được đặt tên cho liên kết dữ liệu trong trình trang trí @propertypressed .
Trước hết, tải trình trang trí @property từ thư viện phần tử ánh sáng và viết mã sau.
import { customElement, property, LitElement, html } from 'lit-element';
@customElement('toggle-button')
export class ToggleButton extends LitElement {
@property({
type: Boolean,
reflect: true
})
pressed = false;
// ...
}
Với LitElement, bạn có thể tùy chỉnh hành vi của các thuộc tính, v.v. và nội dung có thể được đặt dưới dạng một tùy chọn. Điểm lần này là cài đặt được gọi là phản chiếu . Điều này reflectcho phép các thay đổi thuộc tính được phản ánh dưới dạng thuộc tính trong các phần tử tùy chỉnh. Kể từ khi tài sản được thiết lập với Boolean thời gian này true, falsecác thuộc tính được thêm vào khi nào, và thuộc tính sẽ bị xóa khi. Bằng cách này, LitElement cho phép bạn tùy chỉnh hành vi của chính thuộc tính .
Tiếp theo pressed, viết một biểu thức để chuyển đổi từ ngữ của nút trong phần tử tùy chỉnh bằng cách sử dụng thuộc tính đã xác định . Ngoài ra, hãy mô tả thuộc tính @click trong mẫu và liên kết hàm pressedchuyển đổi giá trị boolean của thuộc tính toggle().
Bằng cách này, toggle()hàm sẽ cập nhật thuộc tính mỗi khi bạn nhấp vào nó và truenếu thuộc tính được nhấn có giá trị, pressedthuộc tính sẽ được thêm vào HTML .
Nếu bạn thực thi mã cho đến nay trong trình duyệt, nó sẽ giống như hình chụp sau.
Nếu bạn thực thi mã cho đến nay trong trình duyệt, nó sẽ giống như hình chụp sau. Điều này hoàn thành một thành phần đơn giản.
Build
Lệnh xây dựng như sau.
npm run build
Tại thời điểm xây dựng, Snowpack dịch các thư viện phụ thuộc vào ứng dụng của bạn để chúng có thể được tải bằng cách nhập ESM. Các thành phần được xuất ra build/_dist_/các thư mục và các gói phụ thuộc build/web_modules/được xuất ra.
Snowpack không có trình gói mô-đun theo mặc định và bằng cách giới thiệu @ snowpack / plugin-webpack và @ snowpack / plugin-parcel , được cung cấp dưới dạng plugin chính thức, nó hỗ trợ các trình duyệt cũ không hỗ trợ nhập ESM. Bạn hoàn toàn có thể làm được. Tuy nhiên, developxin lưu ý rằng ngay cả khi cài đặt Bundle, lệnh sẽ được xuất ra bởi Mô-đun ES.
Những Câu Hỏi Nên Hỏi Khi Phỏng Vấn Giúp Ứng Viên Ghi Điểm Với Nhà Tuyển Dụng
Phỏng vấn là quá trình trao đổi thông tin giữa hai bên: ứng viên và nhà tuyển dụng, để cả hai có thêm hiểu biết về nhau và đánh giá được sự phù hợp giữa hai bên. Một câu hỏi quen thuộc mà các ứng viên thường gặp trong quá trình phỏng vấn là “Bạn có câu hỏi gì muốn hỏi chúng tôi không?”, “Bạn muốn tìm hiểu thêm thông tin gì không?”. Đừng bao giờ trả lời “Tôi không có thắc mắc nào”. Hãy tìm hiểu thêm về những câu hỏi nên hỏi nhà tuyển dụng, chúng sẽ giúp bạn ghi điểm đầy ấn tượng trong mắt nhà tuyển dụng đấy.
Biết cách đặt câu hỏi sẽ giúp ứng viên “ghi điểm” với nhà tuyển dụng
Tại sao cần chuẩn bị trước những câu hỏi nên hỏi nhà tuyển dụng?
Có nhiều lý do khác nhau mà ứng viên nên để tâm đến việc chuẩn bị những câu hỏi sẽ hỏi người phỏng vấn. Cách đặt câu hỏi sẽ phản ánh rất chân thật sự quan tâm của ứng viên đến công việc và vị trí họ ứng tuyển. Người phỏng vấn, nhất là những người trực tiếp quản lý nhân sự trong phòng ban sẽ đánh giá rất cao việc ứng viên đặt những câu hỏi liên quan đến công việc chuyên môn hoặc sắp xếp tổ chức trong quá trình làm việc. Những câu hỏi này cho thấy ứng viên thật sự quan tâm và mong muốn có được công việc, vì đã dành nhiều thời gian để tìm hiểu về nó.
Thêm vào đó, nhờ đã tìm hiểu thông tin đủ nhiều và đã có một số câu hỏi liên quan, khi nhà tuyển dụng trả lời câu hỏi của mình, ứng viên có thể dựa vào các vấn đề đó để khai thác các thông tin liên quan khác. Suy cho cùng, mục đích của việc đặt câu hỏi là để ứng viên có thêm thông tin về công ty mà các tìm kiếm trên mạng không có kết quả.
Do đó, đừng bao giờ đặt ra những câu hỏi mà bạn hoàn toàn có thể tìm được câu trả lời trên internet nhé. Hãy cố gắng khai thác tối đa các thông tin từ hai phía để buổi phỏng vấn trở nên thú vị và suôn sẻ hơn thay vì ứng viên chỉ trả lời những câu hỏi của người phỏng vấn.
Những câu hỏi nên hỏi nhà tuyển dụng trong quá trình phỏng vấn
Như đã đề cập, việc đặt câu hỏi là để khai thác thông tin phục vụ cho công việc và quyền lợi ứng viên. Vậy nên không nên đặt những câu hỏi quá đơn giản, câu trả lời chỉ là có hoặc không.
Đặt những câu hỏi liên quan đến chuyên môn công việc
Việc đặt những câu hỏi về chuyên môn công việc chắc chắn là cần thiết để ứng viên có thể hiểu rõ hơn vị trí mình đang ứng tuyển, bản thân có thể đóng góp gì cho công ty từ kinh nghiệm làm việc của bản thân, và có thể học thêm được những gì mới ở công việc này. Một số mẫu câu hỏi mà bạn có thể tham khảo như:
Vị trí này có yêu cầu những kỹ năng đặc biệt gì để hỗ trợ cho công việc không?
Ngoài những gì được mô tả trong JD (Job Description), tôi phải làm thêm những việc nào khác nữa không? Nếu có, những việc đó chiếm bao nhiêu phần trăm trong khối lượng công việc tôi phải đảm nhận?
Lộ trình công việc của công ty với vị trí này như thế nào?
Từ kinh nghiệm của những người đi trước, tôi nên duy trì thói quen nào hoặc chuyên môn nào trong công việc để làm tốt hơn?
Thử thách lớn nhất ở vị trí này là gì?
Đặt những câu hỏi liên quan đến công ty
Công ty nào cũng mong muốn có thể tìm được những nhân viên tài năng và thật sự gắn bó với công ty. Đó cũng là lý do mà nhân sự luôn là phòng ban quan trọng trong việc tìm kiếm nhân tài cho công ty. Đưa ra những câu hỏi liên quan đến công ty và phòng ban làm việc sẽ giúp người phỏng vấn đánh giá được chính xác mong muốn gắn bó của ứng viên với công ty. Và đương nhiên cũng sẽ giúp ứng viên xem xét những mục tiêu của công ty với mục đích nghề nghiệp của bản thân có tương xứng.
Một số câu hỏi ứng viên có thể đặt ra với người phỏng vấn như:
Xu hướng phát triển của công ty trong 5 năm tới như thế nào? Các sản phẩm mà công ty hướng đến nằm trong lĩnh vực chính yếu nào?
Điểm mạnh của công ty là gì?
Phòng ban tôi làm việc chịu trách nhiệm với những công việc nào trong công ty?
Quy mô nhân sự của phòng ban hiện đang như thế nào?
Quản lý đánh giá như thế nào về môi trường là việc tại phòng ban cũng như chất lượng nhân sự?
Có một số câu hỏi mẫu để ứng viên tham khảo
Đặt câu hỏi về quy trình làm việc tiếp theo sau buổi phỏng vấn
Đây chắc chắn là phần quan trọng mà bất cứ ứng viên nào cũng không nên bỏ qua ở cuối mỗi buổi phỏng vấn. Hãy hỏi người phỏng vấn:
Nếu thông qua buổi phỏng vấn này thì bước tiếp theo của quy trình tuyển dụng là gì?
Sau bao lâu tôi sẽ nhận được kết quả phỏng vấn?
Tôi nên giữ liên lạc với ai để nắm được các thông tin sau buổi phỏng vấn này?
Yếu tố quan trọng của một buổi phỏng vấn là sự hòa hợp và thái độ giữa hai phía. Ứng viên có thể linh động dựa vào thái độ của người phỏng vấn để hỏi họ những câu hỏi mang tính cá nhân cũng là một lựa chọn không tồi.
Cá nhân anh/chị đánh giá như thế nào về môi trường làm việc ở công ty?
Anh/chị đã làm việc ở công ty này bao lâu rồi?
Anh/chị có nghĩ mình đã thành công và học được nhiều chuyên môn hơn ở công ty không?
Một số lưu ý khi đặt câu hỏi để tránh mất điểm trong mắt nhà tuyển dụng
Bên cạnh những câu hỏi ứng viên nên hỏi nhà tuyển dụng cũng có một số lưu ý trong quá trình đặt câu hỏi khi phỏng vấn để tránh mất điểm. Đừng đặt những câu hỏi mà câu trả lời ứng viên hoàn toàn có thể tìm kiếm trên mạng, đây chắc chắn là yếu tố rất dễ khiến bạn mất điểm trong mắt nhà tuyển dụng. Việc đặt những câu hỏi như thế này không chỉ khiến hai bên làm mất thời gian của nhau mà còn khiến người phỏng vấn đánh giá thấp sự quan tâm và mong muốn của ứng viên với công ty.
Ngoài ra, ứng viên cũng không nên đặt ra những câu hỏi quá sâu về các hoạt động riêng của công ty. Tốt hơn hết chỉ nên hỏi đến những vấn đề như văn hóa làm việc. Cũng không nên đề cập quá nhiều đến vấn đề lương thưởng nếu nhà tuyển dụng chưa nhắc đến nó. Đừng quá nôn nóng với lương thưởng sẽ giúp nhà tuyển dụng đánh giá cao tinh thần làm việc và mong muốn của bạn hơn.
Mặc dù những vấn đề nên hỏi trong khi phỏng vấn được đề cập ở trên khá nhiều, tuy nhiên bạn nên cân nhắc đặt ra những câu hỏi hợp lí và phù hợp với tình hình công ty. Không nên đặt quá nhiều câu hỏi hay hỏi quá lan man. Hãy hỏi những vấn đề mà bạn cảm thấy quan tâm nhất trong số những câu hỏi nên hỏi nhà tuyển dụng ở trên để buổi phỏng vấn diễn ra suôn sẻ nhất.
Trong các bài viết trước chúng ta đã tìm hiểu về Default Exchange, cách tạo Work Queue với RabbitMQ. Trong bài này, chúng ta sẽ cùng tìm hiểu về Direct Exchange trong RabbitMQ.
Direct Exchange (trao đổi trực tiếp – amq.direct) định tuyến message đến Queue dựa vào routing key.
Một Exchange không xác định tên (empty String), đây là loại Default Exchange, một dạng đặc biệt của là Direct Exchange. Default Exchange được liên kết ngầm định với mọi Queue với khóa định tuyến bằng với tên Queue.
Flow của một Message trong Direct Exchange như sau:
Một Producer sẽ tạo một Message và publish tới Exchange.
Một Queue sẽ binding tới Exchange sử dụng routing key. Chúng ta có thể tạo nhiều Queue và binding tới Exchange, có thể sử dụng cùng routing key, hoặc các routing key khác nhau.
Một Message tới Exchange với thông tin routing key. Dựa vào thông tin routing key, message sẽ được chuyển đến một hoặc nhiều Queue đã binding có cùng routing key với routing key của Message.
Chúng ta đã thấy cách hoạt động của Default Exchange ở các bài viết trước. Trong phần tiếp theo của bài viết này, chúng ta sẽ thấy cách hoạt động của Direct Exchange với routing key cụ thể.
Ví dụ Direct Exchange trong RabbitMQ
Trong ví dụ này, tôi tạo một Direct Exchange có tên GPCoderDirectExchange, tạo 3 Queue binding tới Direct Exchange này với 3 routing key:
QDeveloper sẽ binding với routing key devGroup.
QManager sẽ binding với routing key managerGroup.
QGeneral sẽ binding với routing key generalGroup.
Một số class của chương trình:
ConnectionManager : hỗ trợ tạo Connection đến RabbitMQ.
DirectExchangeChannel : class util hỗ trợ tạo Echange, Queue, binding Queue đến Exchange, publish/ subscribe message, …
Constant : định nghĩa constant chứa các thông tin về tên Exchange, Queue, Routing Key.
Producer: để gửi Message đến Exchange.
Consumer: để nhận Message từ Queue.
App: giả lập việc gửi nhận Message thông qua Direct Exchange của RabbitMQ.
ConnectionManager.java
package com.gpcoder.directexchange;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConnectionManager {
private ConnectionManager() {
super();
}
public static Connection createConnection() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
return factory.newConnection();
}
}
package com.gpcoder.directexchange;
public final class Constant {
// Exchange
public static final String EXCHANGE_NAME = "GPCoderDirectExchange";
// Routing key
public static final String DEV_ROUTING_KEY = "devGroup";
public static final String MANAGER_ROUTING_KEY = "managerGroup";
public static final String GENERAL_ROUTING_KEY = "generalGroup";
// Queue
public static final String DEV_QUEUE_NAME = "QDeveloper";
public static final String MANAGER_QUEUE_NAME = "QManager";
public static final String GENERAL_QUEUE_NAME = "QGeneral";
private Constant() {
super();
}
}
package com.gpcoder.directexchange;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import static com.gpcoder.directexchange.Constant.*;
public class App {
public static void main(String[] args) throws IOException, TimeoutException {
// Create producer
Producer producer = new Producer();
producer.start();
// Publish some message
producer.send("This message for all developers", DEV_ROUTING_KEY);
producer.send("This message for all managers", MANAGER_ROUTING_KEY);
producer.send("This message for everyone", GENERAL_ROUTING_KEY);
Consumer consumer = new Consumer();
consumer.start();
consumer.subscribe();
}
}
Output chương trình:
[Send] [devGroup]: This message for all developers
[Send] [managerGroup]: This message for all managers
[Send] [generalGroup]: This message for everyone
[Received] [QDeveloper]: amq.ctag-F_4tm402_GYRx8FBn6rLPw
[Received] [QDeveloper]: This message for all developers
[Received] [QManager]: amq.ctag-DbVV5-XhzLyFtFd5Kij8DQ
[Received] [QManager]: This message for all managers
[Received] [QGeneral]: amq.ctag-feJgzR4t-P2tjvBWEb13yA
[Received] [QGeneral]: This message for everyone
Như bạn thấy, Consumer/ Producer chỉ gửi/nhận đúng Message ở Queue mà nó binding.
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Các public client như Native mobile application or Single Page Application không thể lưu trữ Client Secret trong Authorization Code grant type một cách bảo mật được. Decode source của mobile application hay view source code của Single Page Application, chúng ta có thể xem được thông tin Client Secret này. Vì thế OAuth giới thiệu Proof Key for Code Exchange (PKCE) extension hỗ trợ cho Authorization Code grant type để giải quyết vấn đề này. Cụ thể như thế nào? Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu về Authorization Code grant type với Proof Key for Code Exchange (PKCE) trong OAuth 2.1 các bạn nhé!
Ý tưởng của PKCE là sử dụng 1 cặp secret code bao gồm Code Challenge và Code Verifier, được generate bởi ứng dụng thứ ba hay còn gọi là Client Application. Client Application sẽ gửi Code Challenge đi cùng với request để lấy authorization code. Authorization server sẽ lưu Code Challenge này lại. Trong request get access token, Client Application sẽ gửi Code Verifier, authorization server sẽ verify Code Challenge và Code Verifier để issue access token.
Workflow của Authorization Code grant type với PKCE, mình có thể diễn đạt như sau:
Như các bạn thấy, Client Secret đã không còn được sử dụng trong grant type Authorization Code với PKCE nữa!
Bài viết được sự cho phép của tác giả Kien Dang Chung
Python khác với các ngôn ngữ lập trình khác, nó đưa ra rất nhiều các cấu trúc dữ liệu dạng đa giá trị, trong bài trước chúng ta đã học về List và Tuple, bài này chúng ta tìm hiểu về hai cấu trúc dữ liệu tiếp theo của Python là Set (tập hợp).
1. Tập hợp (Set)
Set trong Python là một cấu trúc dữ liệu liên quan đến toán tập hợp hay còn gọi là lý thuyết tập hợp do nhà toán học người Đức Georg Cantor đề xuất. Set có thể chứa nhiều các phần tử và các phần tử này không có thứ tự, vị trí của nó hỗn loạn trong tập hợp. Bạn có thể duyệt qua các phần tử trong tập hợp, có thể thêm hoặc xóa đi các phần tử và thực hiện các phép toán tập hợp như phép hợp (union), phép giao (intersection), phép hiệu (difference)…
Các phần tử của tập hợp phải là các dữ liệu không thể thay đổi như một số (int), một chuỗi (string), hoặc một Tuple.
1.1 Khai báo tập hợp
Tập hợp (Set) trong Python có một số tính chất mà bạn cần nhớ:
Các phần tử trong tập hợp không có thứ tự.
Các phần tử này là duy nhất, không cho phép lặp lại.
Set có thể thay đổi (thêm bớt phần tử) nhưng các phần tử của tập hợp phải ở dạng không thể thay đổi (tức là xác định được dung lượng bộ nhớ ngay khi khai báo).
Chúng ta sử dụng các dấu ngoặc nhọn trong khai báo Set, ví dụ:
Các phần tử trong tập hợp có thể thêm hoặc loại bỏ. Python hỗ trợ rất nhiều các phương thức để thực hiện thao tác thay đổi tập hợp.
1.2.1 Phương thức .add()
Phương thức sử dụng để thêm một phần tử vào tập hợp.
Ví dụ:
friends ={"Rolf","Bob","Anne"}
friends.add("Jen")print(friends)# Kết quả là {"Bob","Jen","Anne","Rolf"}
Chú ý, kết quả có thể khác đi do Set không sắp xếp các phần tử theo một trật tự nào cả.
1.2.2 Phương thức .remove()
Loại bỏ một phần tử trong tập hợp.
Ví dụ:
friends ={"Rolf","Bob","Anne"}
friends.remove("Anne")print(friends)# Kết quả là {"Rolf","Bob"}
friends.remove("Jen")print(friends)# Kết quả là lỗi KeyError: "Jen"
Khi loại bỏ một phần tử, nếu phần tử đó không tồn tại trong tập hợp, chương trình sẽ dừng và một thông báo lỗi KeyError xuất hiện.
1.2.3 Phương thức .discard()
Giống như phương thức .remove() loại bỏ phần tử trong tập hợp, tuy nhiên nếu phần tử đó không tồn tại thì nó không báo lỗi gì cả.
friends ={"Rolf","Bob","Anne"}
friends.discard("Anne")print(friends)# Kết quả là {"Rolf","Bob"}
friends.discard("Jen")print(friends)# Kết quả là {"Rolf","Bob"}
1.2.4 Phương thức .pop()
Loại bỏ một phần tử ngẫu nhiên khỏi tập hợp.
friends ={"Rolf","Bob","Anne"}
friends.pop()print(friends)# Kết quả là {"Bob","Rolf"}
Bạn cần chú ý về thứ tự các phần tử trong tập hợp, nó không được sắp xếp theo bất kỳ quy tắc nào.
1.2.5 Phương thức .clear()
Loại bỏ tất cả các phần tử trong tập hợp, khi đó tập hợp được gọi là tập rỗng.
friends ={"Rolf","Bob","Anne"}
friends.clear()print(friends)# Kết quả là set()
1.2.6 Phương thức .update()
Phương thức .add() ở trên chỉ thêm được 1 phần tử vào tập hợp với 1 câu lệnh, để thêm nhiều phần tử, chúng ta sử dụng .update(). Chú ý, đầu vào của .update() có thể là một Set, một List hoặc một Tuple.
friends ={"Rolf","Bob","Anne"}
friends.update(["Jen","Charlie"],{"Jonhny","Sara"},("Laura","Elite"))print(friends)# Kết quả là {'Anne','Laura','Elite','Rolf','Jonhny','Charlie','Bob','Sara','Jen'}
Kết quả của bạn có thể có thứ tự khác đi, một chú ý nữa là không sử dụng chuỗi để cập nhập vào tập hợp mà các phần tử là chuỗi bởi vì chuỗi sẽ được coi là một danh sách các ký tự, ví dụ:
friends ={"Rolf","Bob","Anne"}
friends.update("Jen")print(friends)# Kết quả là {'n','e','Rolf','Bob','Anne','J'}
Không như mong đợi phải không, bạn có thể sử dụng phương thức .add() hoặc có thể chuyển chuỗi thành Set, List hoặc Tuple có 1 phần tử:
friends ={"Rolf","Bob","Anne"}
friends.update(("Jen",))# hoặc
friends.update(["Jen"])# hoặc
friends.update({"Jen"})
Có một số phương thức update khác như .difference_update(), .symmetric_difference_update() hay .intersection_update() nó có liên quan đến các phép toán trong tập hợp nên sẽ trình bày ở phần tiếp theo.
Các tập hợp có lợi thế hơn các cấu trúc dữ liệu khác ở chỗ nó thực hiện được các phép toán tập hợp như hợp, hiệu, giao… Để mô tả dễ hiểu hơn, chúng ta có hai tập hợp art_friends và science_friends là tập hợp các bạn trong lớp Mỹ thuật và tập hợp các bạn trong lớp Khoa học.
Hợp của hai tập hợp cho kết quả là tất cả các phần tử trong hai tập hợp, chú ý phần tử nào lặp lại sẽ chỉ xuất hiện 1 lần trong tập kết quả. Trong Python, để thực hiện phép hợp, chúng ta sử dụng phương thức .union(). Chú ý, sử dụng tập hợp nào trước cũng cho kết quả như nhau, art_friends.union(science_friends) cũng cho kết quả như science_friends.union(art_friends).
art_friends ={"Rolf","Anne","Jen"}
science_friends ={"Jen","Charlie"}
all_friends = art_friends.union(science_friends)print(all_friends)# Kết quả {'Rolf','Anne','Jen','Charlie'}
Chú ý, “Jen” có mặt trong cả hai lớp nhưng với tập kết quả cuối cùng thì “Jen” chỉ xuất hiện 1 lần.
1.3.2 Phép trừ (Difference)
Hiệu của một tập A trừ đi một tập B cho kết quả là tất các phần tử thuộc A nhưng không thuộc B. Sử dụng phương thức .difference() để thực hiện phép trừ hai tập hợp.
art_friends ={"Rolf","Anne","Jen"}
science_friends ={"Jen","Charlie"}
art_but_not_science = art_friends.difference(science_friends)
science_but_not_art = science_friends.difference(art_friends)print(art_but_not_science)# Kết quả {'Rolf','Anne'}print(science_but_not_art)# Kết quả {'Charlie'}
Trong ví dụ trên, tập hợp art_but_not_science chứa các bạn học lớp Mỹ thuật nhưng không học lớp Khoa học, chú ý “Jen” học cả hai lớp nên không có mặt trong tập hợp này.
1.3.3 Hiệu đối xứng của hai tập hợp (Symmetric difference)
Hiệu đối xứng của hai tập A và B được kết quả là tập hợp các phần tử thuộc cả A và B nhưng không đồng thời thuộc cả tập A và B. Phương thức .symmetric_difference() cho kết quả là hiệu đối xứng của hai tập hợp. Chú ý, do tính chất đối xứng nên art_friends.symmetric_difference(science_friends) và science_friends.symmetric_difference(art_friends) cho kết quả như nhau.
art_friends ={"Rolf","Anne","Jen"}
science_friends ={"Jen","Charlie"}
not_in_both_1 = art_friends.symmetric_difference(science_friends)print(not_in_both_1)# Kết quả {'Rolf','Charlie','Anne'}
not_in_both_2 = science_friends.symmetric_difference(art_friends)print(not_in_both_2)# Kết quả {'Rolf','Anne','Charlie'}
1.3.4 Phép giao (Intersection)
Phép giao hai tập hợp cho kết quả là các phần tử đồng thời thuộc cả hai tập hợp. Trong Python sử dụng phương thức .intersection() để thực hiện phép giao, chú ý tập hợp nào đứng trước cũng được, do đó kết quả art_friends.intersection(science_friends) và science_friends.intersection(art_friends) là như nhau.
art_friends ={"Rolf","Anne","Jen"}
science_friends ={"Jen","Charlie"}
art_and_science = art_friends.intersection(science_friends)print(art_and_science)# Kết quả là {"Jen"}
Tập hợp art_and_science chứa các bạn học đồng thời cả lớp Mỹ thuật và lớp Khoa học, do đó kết quả chỉ có “Jen” học cả hai lớp này.
Trong phần trước chúng ta đã biết đến phương thức .update() để thêm nhiều phần tử vào một tập hợp. Dựa vào các phép toán tập hợp, Python cung cấp một số các phương thức khác để thay đổi tập hợp như sau:
.difference_update()
Phương thức này là sự kết hợp của .difference() và .update(). Nó thực hiện phép trừ tập hợp trước, được kết quả như thế nào sẽ cập nhật vào tập hợp đích.
A ={1,2,3,4}
B ={3,4,5,6}
A.difference_update(B)print(A)# Kết quả {1, 2}
.symmetric_difference_update()
Phương thức này là sự kết hợp của .symmetric_difference() và .update(). Nó thực hiện phép trừ đối xứng 2 tập hợp trước, được kết quả như thế nào sẽ cập nhật vào tập hợp đích.
A ={1,2,3,4}
B ={3,4,5,6}
A.symmetric_difference_update(B)print(A)# Kết quả là {1, 2, 5, 6}
.intersection_update()
Tương tự, Python thực hiện .intersection() trước sau đó thực hiện .update():
A ={1,2,3,4}
B ={3,4,5,6}
A.intersection_update(B)print(A)# Kết quả là {3, 4}
1.3.6 Một số các phép toán khác
.isdisjoint() Trả về True nếu hai tập hợp không giao nhau, tức là hai tập hợp không có phần tử chung.
A ={1,2,3,4}
B ={3,4,5,6}print(not A.isdisjoint(B))# Kết quả là True
Ở đây, chúng ta sử dụng toán tử logic not, để thực hiện trả về True khi hai tập giao nhau, nghe nó thuận tai hơn :D.
.issubset() Trả về True nếu tập này còn tập con của tập đích (tập trong ngoặc).
A ={3,4}
B ={3,4,5,6}print(A.issubset(B))# Kết quả là True
.issuperset() Trả về True nếu tập này là tập cha của tập đích (tập trong ngoặc).
A ={3,4}
B ={3,4,5,6}print(A.issuperset(B))# Kết quả là False
Ngoài ra chúng ta có thể sử dụng các ký hiệu phép toán so sánh thông thường để kiểm tra xem là tập con, tập cha hay hai tập bằng nhau với >, >=, ==, <, <=.
A ={3,4}
B ={3,4,5,6}print(A.issubset(B))# Kết quả là True
# Tương đương với
print(A <= B)# Kết quả là True
Python cung cấp một hàm tên là frozenset(), kết quả trả về là một tập hợp (Set) không thể thay đổi. Khi đó, nếu bạn thực hiện các phương thức .add(), .remove(), .update()… sẽ báo lỗi.
“Đóng băng” tập hợp sẽ làm cho tập hợp đó giống như cấu trúc Tuple trong Python.
friends ={"Rolf","Anne","Jen"}
frozen_friends =frozenset(friends)
frozen_friends.add({"Jen","Charlie"})print(frozen_friends)# Kết quả lỗi: AttributeError: 'frozenset' object has no attribute 'add'
Đóng băng một tập hợp rất hữu ích trong trường hợp bạn muốn tập hợp đó không thể thay đổi. Ví dụ khi dùng một tập hợp làm key cho một từ điển (Dictionary), sẽ được giới thiệu trong phần tiếp theo.
A ={1,2,3}
B ={'a','b','c'}
C ={x:'foo', y:'bar'}# Kết quả lỗi: TypeError: unhashable type: 'set'
Tuy nhiên nếu bạn đóng băng các tập hợp này, sẽ không có lỗi nào xảy ra.
A =frozenset({1,2,3})
B =frozenset({'a','b','c'})
C ={x:'foo', y:'bar'}# Không có lỗi
2. Tập hợp sử dụng khi nào?
Toán tập hợp hay lý thuyết tập hợp là một trong những phần quan trọng của Toán học mà Khoa học dữ liệu (data science) và Machine Learning sử dụng kiến thức Toán rất nhiều, do vậy toán tập hợp trong Python là một phần không thể thiếu. Ngay từ đầu Python đã được phát triển cho mục đích Khoa học và Giáo dục, do vậy bạn có thể thấy các thiết kế mang hơi hướng Khoa học.
Tập hợp cũng là một nhóm các dữ liệu giống như với List và Tuple nhưng nó lại được xây dựng sẵn các phép toán tập hợp, do vậy tập hợp sẽ được sử dụng khi chương trình của bạn cần các phép toán tập hợp như .union(), .difference(), .intersection()… Để lựa chọn cấu trúc dữ liệu phù hợp, bạn cần nắm rõ những đặc điểm của từng loại, ở đây Set có những đặc điểm mà tôi đã đưa ra ở phần đầu, dưới đây chỉ nhắc lại:
Set có các phần tử là không được thay đổi, do vậy khả năng tìm dữ liệu sẽ nhanh hơn.
Set cần thiết cho các logic liên đến các cặp (key:value) trong cấu trúc Dictionary của Python.
Các phần tử là duy nhất, do đó nếu bạn có một dữ liệu tương tự thì Set là một lựa chọn.
Web components là một tập các quy chuẩn công nghệ dùng cho việc xây dựng các thành phần web được đóng gói (tách biệt với phần code còn lại của ứng dụng như View / Back For Front của server side reder) và có thể tái sử dụng cho client side (nôm na là nén thành cục javaScript for browser và tự render linh hoạt) thường sẽ áp dụng SPA.
Về cơ bản web components sử dụng 3 công nghệ cốt lõi:
Custom Elements: là tập hợp các API của Javascript để cho phép tạo ra các thành phần web tuỳ chỉnh.
Shadow DOM: là tập hợp các API của Javascript để gắn một cây DOM “shadow” (như shadow object trong javaScript) vào một thành phần của DOM, cây DOM này được quản lý riêng biệt và render riêng với cây DOM chính, do vậy nó có thể được đóng gói lại để sử dụng cho các ứng dụng khác nhau.
HTML templates: Dùng để tạo ra các template từ đó được render ra trang web. Khái niệm này được một số framework như Angular (Google) hay React (Facebook) phát triển.
Vậy là Lit đã được tạo ra để tích hợp các công nghệ Web component đúng không? Ummmm
Lit is a simple library for building fast, lightweight web components.
At Lit’s core is a boilerplate-killing component base class that provides reactive state, scoped styles, and a declarative template system that’s tiny, fast and expressive.
Như mình hiểu thì Lit là một thư viện cho việc xây dựng nhanh gọn web components tiêu chuẩn của google đề xuất và phát triển.
Với thư viện gọn nhẹ thì bạn sẽ dễ dàng tích hợp cho các framework hiện tại của bạn mà không phải tốn quá nhiều effort cho việc chuyển đổi công nghệ qua Vue, ReactJS mà vẫn có các tính năng linh hoạt cao như Vue hoặc ReactJS.
Điều khác biệt mà Lit mang lại so với Vue, ReactJS là gì??? Sau thời gian trải nghiệm các dự án sử dụng Vue, React và Lit thì thấy ở Lit nổi bật là giảm thiểu tình trạng lock-in, tối đa được tính linh hoạt và khả năng maintain tốt hơn với việc sử dụng mô hình browser’s native. Với site render lượng lớn component kết hợp server site render của React sẽ thấy khác biệt rõ rệt sau khi chuyển qua Lit… oh my goodness, oh my goodness gọi ajax rồi render page nhanh quá dậy.
Khi bạn phát triển ứng dụng bằng Lit, bạn có thể dễ dàng tích hợp các web components libraries khác. Bạn thậm chí có thể update version mới của Lit hoặc chuyển sang thư viện khác lúc phát triển mà không ảnh hưởng nhiều tới quá trình phát triển product. Còn dùng Vue hay React thì migration version thôi cũng phát ngán rồi, còn các tính năng và lifecycle mới phải học nửa…
Tuy nhiên đó chỉ là quan điểm cá nhân mình trên dự án có business phức tạp thôi còn tuỳ mức độ và business của dự án nửa mới phán đoán Lit có phù hợp hay không
Giới thiệu tới đây thôi còn muốn đào sâu hơn thì mình sẽ có bài viết khác về migration hệ thống dùng Lit.
Làm việc với MongoDB, thông thường là làm việc với dữ liệu lớn, do đó cần chuẩn bị cơ sở dữ liệu có kích thước tương đối lớn để sát với thực tế sử dụng. Tải về từ server SmartJob 2 cơ sở dữ liệu mẫu, bấm vào để download
– zips: Cơ sở dữ liệu về mã số bưu cục tại Mỹ (file download 567 KB, sau giải nén 3,03 MB, dữ liệu thật, hoàn toàn sát với thực tế).
– dataset: Cơ sở dữ liệu thông tin về quán ăn, nhà hàng (file donwload 1,5 MB, sau giải nén 11,6 MB)Sau khi download về, bạn giải nén ra.
Import collection có tên zips vào vào CSDL test (test là CSDL có sẵn sau khi cài đặt MongoDB)
Khi sử dụng tiện ích RockMongo để import dữ liệu, thời gian import rất lâu và dễ bị lỗi. Việc sử dụng câu lệnh là rất tốt, nhanh, tránh được lỗi.
Trong Hệ quản trị Cơ sở dữ liệu MongoDB sẽ có nhiều CSDL, do đó bạn cần khai báo sẽ sử dụng CSDL nào. Gõ lệnh
usetest;
Để sử dụng CSDL test
Gõ lệnh dưới đây để xem nội dung collection “zips” của Cơ sở dữ liệu “zips”. (Đây chính là câu lệnh hiển thị toàn bộ nội dung của collection zips)
db.zips.find().pretty();
Do lượng dữ liệu lớn, cửa sổ dòng lệnh không thể liệt kê hết. Để xem thêm trang sau, bạn gõ
it
rồi nhấn phím Enter.
Công tác chuẩn bị dữ liệu đã sẵn sàng để bạn tạo các truy vấn từ đơn giản đến phức tạp.
TRUY VẤN THEO ĐIỀU KIỆN
Tìm bưu cục có id = 01002, do tìm theo id, nên sẽ trả về không quá 1 document
db.zips.find({"_id":"01002"});
Để tìm document chứa dữ liệu về bưu cục vill
db.zips.find({"city":"GILBERTVILLE"});
Các bạn tham khảo mã nguồn sử dụng Spring Data Mongo để C.R.U.D. (Create – Read – Update – Delete) dữ liệu MongoDB tại: https://github.com/SmartJobVN/MongoDB_SpringDataMongo
Đỗ Như Vý – Bài viết gốc được đăng tải tại smartjob.vn
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Chúng ta sử dụng Dockerfile để cấu hình và build các Docker Image. Để run các Docker container từ các Docker Image này, các bạn có thể sử dụng command line hoặc Docker Compose. Lợi ích của Docker Compose là giúp các bạn có thể định nghĩa và run nhiều Docker container cùng một lúc. Cụ thể như thế nào? Mình sẽ hướng dẫn các bạn cách định nghĩa và run các Docker container với Docker Compose các bạn nhé!
Để làm ví dụ cho bài viết này, mình sẽ tạo mới một Spring Boot project đơn giản, có khai báo sử dụng database nhưng sẽ không có thao tác nào đến database cả, tương tự như bài viết Deploy ứng dụng Spring Boot sử dụng Docker, như sau:
Kết quả:
SpringBootDockerComposeApplication:
package com.huongdanjava.springboot;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.jdbc.metadata.HikariDataSourcePoolMetadata;
import org.springframework.web.bind.annotation.RequestMapping;
import com.zaxxer.hikari.HikariDataSource;
@SpringBootApplication
public class SpringBootDockerComposeApplication {
@Autowired
private DataSource dataSource;
@RequestMapping("/hello")
public String helloDockerCompose() {
Integer idleConnection = new HikariDataSourcePoolMetadata((HikariDataSource) dataSource).getIdle();
return "Hello Docker Compose! Idle connection to database is " + idleConnection;
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDockerComposeApplication.class, args);
}
}
Để có thể sử dụng Docker Compose, chúng ta cần build Docker Image cho ứng dụng của mình. Điểm khác biệt ở đây là chúng ta không cần phải khai báo biến môi trường của ứng dụng trong Dockerfile, chúng ta sẽ sử dụng Docker Compose để làm điều này.
Mình sẽ tạo mới một tập tin Dockerfile trong project ví dụ:
Nội dung tập tin Dockerfile cho ứng dụng của mình như sau:
Sau khi đã có Docker Image cho ứng dụng của mình, các bạn có thể sử dụng Docker Compose để deploy ứng dụng của mình. Như mình đã nói, lợi ích lớn nhất của Docker Compose là giúp chúng ta có thể cấu hình và chạy nhiều Docker Image cùng 1 lúc.
Để minh hoạ điều này, mình sẽ không sử dụng PostgreSQL ở máy local của mình nữa. Mình sẽ viết một Docker Compose có thể cài đặt mới một PostgreSQL và sau đó sẽ chạy ứng dụng của mình lên.
Nhưng trước tiên, chúng ta hãy nói một ít về Docker Compose đã các bạn nhé!
Docker Compose thông thường sử dụng tập tin .yml để định nghĩa.
Mặc định, Docker sử dụng tập tin có tên là docker-compose.yml để chạy Docker Compose, nên mình sẽ tạo mới một tập tin docker-compose.yml trong project ví dụ như sau:
Đầu tiên, các bạn có thể sử dụng thuộc tính version để định nghĩa version của Docker Compose mà chúng ta sẽ sử dụng. Các bạn có thể tham khảo về version của Docker Compose tại đây.
Mình sẽ khai báo sử dụng Docker Compose version 3.8 như sau:
version: '3.8'
Mỗi Docker Container là một service trong tập tin Docker Compose và chúng ta sẽ sử dụng thuộc tính services cùng với khai báo tên của từng service cho các Docker Container của chúng ta. Mình sẽ khai báo như sau:
services:
postgresql:
spring_boot_docker_compose:
Nhiệm vụ của chúng ta là khai báo thông tin cho mỗi service. Các bạn có thể sử dụng một số thuộc tính phổ biến sau để khai báo cho mỗi service như sau:
image: Docker Image mà chúng ta sẽ sử dụng để chạy container.
container_name: tên của container.
restart: các bạn xem thêm ở đây. Thông thường chúng ta sẽ cấu hình cho thuộc tính này là on-failure và số lần restart nếu container start failed.
environment: khai báo các biến môi trường cần thiết cho mỗi container.
volumes: mount thư mục giữa máy chạy Docker và container.
ports: mapping port giữa máy chạy Docker và container.
depends_on: chỉ ra sự phụ thuộc của service này với service khác trong Docker Compose. Container với name được khai báo trong thuộc tính này bắt buộc phải available trước thì service này mới được chạy.
networks: định nghĩa một network dùng chung cho các container. Thông thường chúng ta sẽ sử dụng driver bridge cho phần network này.
Chúng ta sẽ định nghĩa service cho postgresql trước. Mình sẽ định nghĩa như sau:
Các bạn có thể tham khảo thêm bài viết Cài đặt PostgreSQL server sử dụng Docker để hiểu thêm các cấu hình cho service postgresql này.Còn ứng dụng ví dụ, mình sẽ định nghĩa như sau:
Vì phải có database thì ứng dụng ví dụ của chúng ta mới chạy được nên mình sử dụng thuộc tính depends_on trong service spring_boot_docker_compose để khai báo sự phụ thuộc này.
Cả 2 service mà mình đã định nghĩa ở trên sử dụng chung networks là huongdanjava với driver bridge. Chúng ta cần định nghĩa phần networks này như sau:
networks:
huongdanjava:
driver: bridge
Toàn bộ nội dung của tập tin docker-compose.yml như sau: