Trong phần 1, TopDev đã đề cập với các bạn về việc tự nhìn nhận giá trị bản thân và hiểu được mong muốn từ nhà tuyển dụng. Bài viết hôm nay sẽ có những phân tích sâu hơn về cách thức giải quyết thách thức từ nhà tuyển dụng: Mục tiêu phát triển nào bạn đặt ra vào năm 5 tới?
Mọi thách thức được đặt ra như nhằm mục đích khai thác mục tiêu phát triển của mỗi ứng viên. Bằng cách đưa ứng viên vào các tình thế áp lực trong buổi phỏng vấn, nhà tuyển dụng muốn thấy được năng lực thật sự của họ.
Hãy lưu tâm và nắm bắt những điều sau đây nhé! Vì nó có thể giúp bạn trả lời được thách thức từ nhà tuyển dụng đấy.
Đâu là đích đến trong cuộc sống của bạn?
Tại sao phải trả lời câu hỏi này? Nếu đọc kỹ phần 1, bạn dễ nhận thấy đích đến trong cuộc sống có mối liên quan lớn đến các giá trị bạn đang sở hữu. Vấn đề nằm ở chỗ bạn có nhận ra được nó hay không?
Do vậy, hãy bắt đầu đặt câu hỏi tại sao với những gì bạn đang theo đuổi. Bạn học tiếng anh hay một ngoại ngữ khác bên cạnh chuyên môn, vì sao vậy? Không phải bạn muốn tạo ra thế cân bằng trong cuộc chơi nghề nghiệp hay sao?
Bạn tham gia nhiều sự kiện, workshop về công nghệ, gặp gỡ các chuyên gia đầu ngành nhằm mục đích trau dồi thêm kiến thức bổ trợ cho quá trình làm việc sau này. Dù thứ bạn làm nhỏ nhặt hay to lớn, tất cả đều phải có một đích đến. Đó chính là nơi hoài bão của bạn được thực hiện.
24 tiếng trong 1 ngày vẫn cứ thế trôi qua. Liệu bạn đã từng dành cho bản thân một ít thời gian để ngẫm lại: Bạn mong muốn điều gì? Bạn làm gì để thực hiện nó? Bạn cần có thêm những gì để đủ bản lĩnh theo đuổi và thực hiện ước mơ?
Điều quan trọng là bạn cần nhận ra niềm vui với những thứ bạn theo đuổi. Hãy sống để trải nghiệm, đừng sống chỉ để tồn tại.
Hoạch định các mục tiêu phát triển cụ thể
Tại sao phải lên kế hoạch thực hiện các mục tiêu?
Bạn khó chạm đến thành công nếu chỉ dựa vào các mục đích. Xác định được mục đích là điều tất nhiên phải thực hiện. Song, việc tìm ra các mục tiêu cụ thể lại rất quan trọng.
Việc hoạch định các mục tiêu giúp bạn tập trung hơn vào quá trình khai thác bản thân. Bạn sẽ biết mình cần làm gì để thiết lập các mục tiêu cụ thể. Từ các mục tiêu, bạn có những kế hoạch rõ ràng hơn tương ứng với từng nhiệm vụ.
Không những thế, bạn còn chủ động hơn trong việc tìm các yếu tố phù hợp với bản thân. Đồng thời, bạn biết cách phân bổ chúng hợp lý để thuận tiện trong việc tiếp thu những cái mới. Đó là nước đi thông minh để đảm bảo quá trình giải quyết nhiệm vụ không bị gián đoạn.
Chẳng hạn như bạn muốn trở thành một lập trình viên giỏi, bạn cần phải biết những kỹ năng nào cần rèn luyện. Tiếp thu các kiến thức nền tảng về ngôn ngữ lập trình là bước đi đầu tiên.
Bên cạnh đó, bạn đã sẵn sàng tâm lý để đối mặt với những áp lực trong ngành hay chưa? Hãy lập kế hoạch thực hiện các mục tiêu vì nó là cơ sở quyết định mức độ thăng tiến của bạn trên hành trình nghề nghiệp.
Mục tiêu phát triển ngắn hạn và dài hạn
Đừng lo sợ, hãy đặt ra 3 mục tiêu cho bản thân gồm: Mục tiêu ngắn hạn và mục tiêu dài hạn. Tất nhiên, các mục tiêu phát triển đều phải liên quan đến sự nghiệp của bạn.
– Mục tiêu ngắn hạn là được bạn lên kế hoạch; triển khai thành các nhiệm vụ có mối liên hệ với nhau. Bạn cần đảm bảo hoàn thành chúng từ 1-2 năm hoăc 2-3 năm. Tùy vào khả năng mỗi người, nó có thể kéo dài hơn. Song, mọi thứ đều có giới hạn riêng và mục tiêu ngắn hạn cũng không ngoại lệ. Đừng để tình trạng trì trệ xảy ra. Đây là khoảng thời gian bạn nên tập trung vào những việc nhất thiết phải thực thi, tránh làm ảnh hưởng đến tiến độ phát triển.
– Đối với mục tiêu dài hạn, bạn cần tích lũy đủ vốn kinh nghiệm. Đồng thời, đợi đến một thời gian chín muồi để phát triển bản thân một cách toàn diện
Hãy quan tâm đến sự thăng tiến!
Những mục tiêu đã có, những kế hoạch thực hiện đã được hoàn thiện. Vậy làm thế nào để bạn đạt được những mục tiêu đó? Điểm mấu chốt chính nằm ở sự thăng tiến. Thăng tiến trong sự nghiệp chính là đích đến của nhiều người, dù ở bất cứ lĩnh vực nào. Và tất nhiên để đạt được sự thăng tiến, bạn cần trải qua từng giai đoạn và chạm đến từng nấc thang khác nhau trong sự nghiệp.
Chằng hạn như mô tả chặng đường phát triển của một ứng viên trong ngành nhân sự. Nếu may mắn trúng tuyển vào vị trí nhân viên tuyển dụng. Từ đây, họ cần đặt ra những nấc thang trên hành trình vươn tới đỉnh cao sự nghiệp.
Hiên thực hóa sự thăng tiến bằng những “nấc thang nỗ lực”
Những nấc thang đầu tiên, bạn cần phải đảm nhận hoàn hảo các nhiệm vụ của một nhân viên tuyển dụng. Bạn có thể trải nghiệm các khóa học nâng cao chuyên môn. Điều này tạo ra cơ hội để bạn biết thêm nhiều kỹ năng như: quản lý, tổ chức, điều phối, hoạch định chiến lược nhân sự,…
Các vị trí trưởng phòng/chuyên viên nhân sự, giám đốc nhân sự, lãnh đạo nhân sự cấp cao,… đều là đích đến mà nhiều người ao ước. Và tất nhiên, mọi thứ đều được đánh đổi bằng sự nỗ lực.
Thực tế cho thấy, nếu bạn không muốn thăng tiến thì môi trường sẽ thúc đẩy bạn. Chính môi trường làm việc với sức ép cạnh tranh lớn, tự bạn sẽ phải nỗ lực để thăng tiến. Kỹ năng là một thứ quan trọng đảm bảo về chất lượng chuyên môn của bạn. Tuy nhiên, để đạt đến những mục tiêu cao hơn, cái bạn cần nhiều hơn thế. Bạn thật sự phải quan tâm đến nhiều yếu tố khác nhau như: giao tiếp, xây dựng – phát triển các mối quan hệ, lãnh đạo – quản lý con người,..
Hãy đi lên bằng sự cố gắng! Mỗi nấc thang là mỗi mục tiêu bạn cần vượt qua để chứng minh rằng sự thăng hoa trong sự nghiệp của bạn là đều có lý do.
Lời kết
Chính các giá trị bạn đang sở hữu sẽ giúp bạn nhận ra được đâu là thế mạnh bạn cần phải phát huy. Hãy vạch ra cho bản thân các kế hoạch cụ thể để chinh phục những mục tiêu. Khi hiểu được tầm quan trọng của việc nhận ra các giá trị, bạn sẽ biết cách phát huy tiềm năng mình một cách tốt nhất.
Thách thức: Mục tiêu nào bạn đặt ra vào 5 năm tới sẽ không còn là khó khăn đối với bạn nữa. Cách trả lời phù hợp nhất – thông minh nhất sẽ đến từ cách thức bạn thể hiện bản thân có những gì. Và quan trọng, TopDev hi vọng bạn phải thật sự sống đúng với những điều bản thân mình theo đuổi.
Đây là bài viết mở đầu trong series bài viết về đề tài Distributed Systems. Dự định của mình là sẽ thực hiện loạt bài viết tương đối chuyên sâu về các chủ đề: Distributed Systems, Microservices, Transactions, Event sourcing, CQRS, Domain Driven Design, và nếu có thời gian, có thể sẽ đề cập đến cả Blockchain nữa.
Một “hệ thống phân tán” (Distributed Systems-từ giờ xin được phép sử dụng từ gốc tiếng Anh) được định nghĩa là một tập hợp các tiến trình điện toán (process) độc lập, được kết nối với nhau bởi một hệ thống mạng (network) để các process này có thể truyền nhận thông tin (‘process’ ở đây được định nghĩa là một đơn vị điện toán được vận hành với một không gian bộ nhớ-memory space-riêng biệt, không trùng lặp với các process khác). Các process này phối hợp hoạt động với nhau như một thực thể duy nhất đối với người dùng bên ngoài nhằm thực thi một nhiệm vụ nào đó. Dựa theo định nghĩa này thì nhiều process trên cùng 1 máy tính cũng có thể được coi như Distributed Systems (DS). Dĩ nhiên trên thực tế, người ta quan tâm đến việc vận hành nhiều máy tính cùng với nhau, cho nên chúng ta có thể ngầm hiểu là các process này chạy trên các máy tính riêng biệt.
Vậy tại sao chúng ta cần tìm hiểu về DS? DS xuất hiện rất phổ biến trên thực tế. Hầu hết các ứng dụng ngày nay, đặc biệt là các ứng dụng Internet, đều được triển khai dưới dạng DS. Việc triển khai phần mềm, đặc biệt là những hệ thống lớn, trên nhiều đơn vị máy tính (thay vì chỉ dùng một máy tính duy nhất) có rất nhiều lợi ích, VD như:
Cung cấp nhiều tài nguyên hơn khi hệ thống cần xử lý lượng công việc lớn hơn.
Chỉ dùng một đơn vị máy tính đồng nghĩa với rủi ro phần mềm bị sập (crash) nếu máy đó gặp sự cố. Dùng nhiều đơn vị máy sẽ cho phép bạn tiếp tục vận hành phần mềm kể cả khi sự cố xảy ra.
Khi hệ thống của bạn trở nên phức tạp và cần sự kết hợp từ nhiều thành phần khác nhau, sử dụng DS cho phép bạn chia nhỏ một hệ thống to thành nhiều đơn vị nhỏ. Mỗi đơn vị có thể hoạt động độc lập, thậm chí có thể được phát triển bởi các team khác nhau với các chuyên môn khác nhau.
Người dùng hệ thống có thể có sự phân tán về mặt địa lý trên toàn cầu. Để đảm bảo chất lượng dịch vụ và hạn chế độ trễ thì hệ thống máy cũng cần được phân tán để có thể có mặt ở gần người dùng nhất có thể.
Xây dựng Distributed Systems có gì khó ?
Tuy mang đến nhiều lợi ích như kể trên, DS cũng làm cho việc phát triển và vận hành trở nên phức tạp hơn, do đặc tính phân tán của nó. Để xây dựng một hệ thống DS hoạt động tốt, chúng ta sẽ phải giải quyết rất nhiều bài toán, tùy thuộc vào đặc thù của hệ thống đó. Có thể kể ra một vài bài toán thường gặp như:
Bài toán về xử lý sự cố (failure): Với một hệ thống máy tính lớn thì việc máy móc gặp trục trặc hay sự cố là điều thường xuyên xảy ra. Xử lý sự cố để không làm ảnh hưởng đến hệ thống (hoặc ít ra là giảm thiểu ảnh hưởng) là vấn đề cốt lõi nhất trong việc xây dựng DS.
Vấn đề đồng thuận về dữ liệu (consensus): Xây dựng DS đồng nghĩa với việc dữ liệu của hệ thống cũng sẽ bị phân tán. Điều này gây ra trở ngại nếu chúng ta muốn hệ thống làm việc như một thực thể thống nhất, vì các máy đôi khi sẽ bất đồng với nhau về mặt dữ liệu.
Vấn đề bất đồng bộ về mặt thời gian: Mỗi máy tính trong hệ thống có một đồng hồ riêng biệt, và không nhất quán với nhau về mặt thời gian. Đồng hồ máy tính cũng thường xuyên xảy ra tình trạng chạy lệch pha (clock drift). Sự bất đồng bộ này có thể dẫn đến sai lệch về mặt logic của hệ thống. VD như, nếu một ứng dụng nhắn tin không thống nhất được về mặt thời gian, thứ tự tin nhắn của người dùng có thể sẽ sai lệch giữa người dùng này với người dùng kia.
Các vấn đề khác như vấn đề bảo mật, vấn đề giao tiếp, vấn đề lưu trữ và sao lưu dữ liệu…
Có một điều thú vị trong lĩnh vực DS, đó là các bài toán kể trên hầu như không có lời giải lý thuyết nào đáp ứng được yêu cầu một cách hoàn hảo trên (sẽ được bàn luận sâu hơn trong các bài sau). Tuy nhiên điều này không có nghĩa là chúng không có những cách giải quyết phù hợp trong thực tế, tùy vào từng hệ thống cụ thể. Hầu hết các tiến triển gần đây trong lĩnh vực DS đều nhắm đến việc xây dựng những lời giải thực tế cho những hệ thống với mục đích cụ thể.
Các kiểu sự cố trong Distributed Systems
Như đã nói ở trên, sự cố trong vận hành hệ thống xảy ra một cách thường xuyên. Sau đây là đoạn lược dịch lời Jeff Dean, một kĩ sư trưởng tại Google:
Trong trung tâm dữ liệu (data center) của Google, mỗi năm một cluster sẽ xảy ra khoảng 1000 sự cố máy, hàng ngàn sự cố ổ cứng, trung bình một sự cố về nguồn điện khiến cho khoảng 500-1000 server bị sập trong vòng khoảng 6 tiếng đồng hồ. Ngoài ra, trung bình 5 rack sẽ gặp trục trặc, làm mất đi một nửa số packet được truyền tải, làm ảnh hưởng đến khoảng 5% số server tại bất kì thời điểm nào.
Vì sự cố xảy ra thường xuyên như vậy, nên các hệ thống DS cần có cơ chế tự động xử lý khi gặp phải tình huống xấu, vì không phải lúc nào con người cũng có thể can thiệp một cách kịp thời. Để giải quyết được vấn đề này thì chúng ta cần hiểu được hệ thống có thể gặp phải những kiểu sự cố nào.
Sự cố về máy (node failure)
Mỗi máy tính vật lý, do nhiều nguyên nhân khác nhau, có thể gặp sự có trong khi hoạt động. Người ta chia các sự cố này thành một vài loại chính:
Fail-stop: Đây là kiểu sự cố khiến cho process trên máy dừng hoạt động (dừng tính toán cũng như truyền nhận tin). Nguyên nhân sự cố này có thể do máy bị sập (lỗi phần mềm, lỗi hệ điều hành …), lỗi phần cứng, hay những nguyên nhân bên ngoài (vd như mất điện chẳng hạn). Đây là kiểu sự cố thường gặp nhất, nên khi người ta nói đến ‘failure’ mà không nhắc gì thêm thì thường được ngầm hiểu là kiểu sự cố này. Hầu hết các thuật toán được phát triển trong DS đều nhằm đối phó với kiểu sự cố này.
Fail-recover: Process có thể ngừng hoạt động trong một thời gian nhất định, nhưng sau đó phục hồi hoạt động trở lại. Nguyên nhân của kiểu sự cố này có thể là do máy tự động reboot do một nguyên nhân nào đó. Thường khi nhắc đến kiểu sự cố này, người ta mặc đình rằng máy có khả năng lưu trữ thông tin vào ổ đĩa cứng và phục hồi thông tin này sau khi sự cố xảy ra.
Byzantine failure: Sự cố mà máy tính không hoạt động theo đúng yêu cầu đề ra. VD như, máy có thể gửi tin tùy ý, hay thay đổi trạng thái tùy ý, không giống những gì được lập trình. Đây là kiểu sự cố khó chịu nhất, có thể xảy ra khi hệ thống gặp trục trặc không rõ nguyên nhân (vd như RAM có thể bị hỏng khiến xảy ra tình trạng bit-flip), hay do hệ thống bị kể xấu tấn công.
Sự cố về network
Mạng máy tính cũng là một sản phẩm vật lý và vì vậy cũng có thể xảy ra sự cố. Một kiểu sự cố thường gặp là sự cố “chia cắt mạng” (network partitioning), được mô phỏng bởi hình trên. Sự cố này xảy ra đường truyền của một hoặc nhiều server bị chia cắt khỏi phần còn lại của hệ thống, khiến hệ thống bị chia cắt thành nhiều phần không thể giao tiếp với nhau. Trên thực tế, trong các data center, một cluster máy chủ thường được kết nối với nhau bởi một hoặc nhiều cục switch. Sự cố của cổng switch hoặc dây dẫn có thể dẫn đến việc một hay nhiều server bị ngắt kết nối, dẫn đến tình trạng partitioning kể trên.
Ngoài ra, một vài sự cố mạng khác có thể kể ra như việc latency bị tăng cao (do congestion control), hay network adapter của các server gặp trục trặc …
Thiết kế Distributed Systems để sẵn sàng xử lý các sự cố
Do sự cố xảy ra thường xuyên và đa dạng như đã kể trên, hệ thống DS cần được thiết kế để có cơ chế tự động xử lý sự cố, đảm bảo việc vận hành không bị gián đoạn hay sai sót. Sau đây mình sẽ trích đoạn một bài báo khoa học có tên là “Về việc thiết kế và triển khai các dịch vụ Internet”, của tác giả James Hamilton (khi đó làm việc tại Microsoft, hiện tại là kĩ sư trưởng tại Amazon Web Service):
Thiết kế hệ thống để xử lý sự cố là khái niệm cốt lõi khi phát triển các dịch vụ quy mô lớn, bao gồm nhiều thành phần nhỏ. Những thành phần này sẽ thường xuyên gặp sự cố, và đôi khi sự cố này có thể dẫn đến sự cố kia. Khi hệ thống được triển khai trên khoảng 10,000 server và 50,000 đơn vị đĩa cứng, sự cố sẽ xảy ra nhiều lần trong một ngày. Nếu sự cố nào cũng cần đến con người can thiệp, hệ thống sẽ không thể vận hành một cách trơn tru và tiết kiệm được chi phí. Do đó, hệ thống cần có cơ chế đối phó với sự cố mà không cần con người can thiệp. Cơ chế này cần được kiểm tra một cách thường xuyên. Một cách đơn giản để kiểm tra là cố tình gây ra sự cố thường xuyên trong quá trình vận hành hệ thống. Điều này thoạt nghe có vẻ vô lý, tuy nhiên, nếu cơ chế sự cố không thường xuyên được sử dụng thì chúng sẽ không hoạt động khi cần thiết.
Nói thế để thấy rằng, khi phát triển một hệ thống DS, vấn đề sự cố luôn phải được coi như một phần của bài toán, và chúng ta tuyệt đối không được mặc định rằng sự cố không bao giờ xảy ra.
Một vài tài liệu & đường link để tìm hiểu sâu thêm về Distributed Systems
Distributed Systems là một lĩnh vực tương đối sâu rộng và trong một vài bài viết thì khó mà chúng ta có thể đề cập chi tiết hết về các chủ đề được. Sau đây mình chia sẻ một vài nguồn thông tin để các bạn có thể tìm hiểu sâu hơn về lĩnh vực này:
Bài viết được sự cho phép của tác giả Trần Duy Thanh
Ở bài 2 các bạn đã biết cách tạo 1 Project trong Android Studio rồi. Nhưng làm thế nào để chạy được phần mềm này lên điện thoại? Đâu phải ai cũng có điện thoại đúng không? làm thế nào để không có điện thoại mà vẫn test phần mềm bình thường?
Bài này Tui sẽ hướng dẫn các bạn cách thức tạo một Điện thoại giả lập trong Android Studio để thay thế điện thoại thật. Giúp bạn tiết kiệm chi phí mà vẫn học được bình thường.
Và Lưu ý thêm, từ Android 5.0 thì máy tính phải hỗ trợ ảo hóa, do đó các bạn nhớ kích hoạt ảo hóa lên nhé. Thường các dòng máy mới thì nó có sẵn tính năng này, nhưng đôi khi nó vẫn chưa được kích hoạt lên trước nhé, tùy dòng máy là chuẩn BIOS hay chuẩn UEFI mà các bạn tìm chỗ chỉnh, xem bài này để kích hoạt ảo hóa.
Từ màn hình trong bài 2, ta chọn AVD Manager (có 2 cách):
Vào Menu Tools-> chọn AVD Manager
hoặc nhấn biểu tượng AVD Manager trên thanh toolbar
Lúc này màn hình Android Virtual Device Manager sẽ hiển thị ra như dưới đây:
Ở màn hình trên, bạn thấy Android Studio của Tui có sẵn 3 điện thoại giả lập (do Tui làm trước đó).
Của bạn thì không có gì nha vì chưa tạo bao giờ. Bạn sẽ nhấn vào nút “Create Virtual Device”, màn hình Virtual Device Configuration sẽ xuất hiện ra như dưới đây:
Trong mục Category chọn Phone
Trong danh sách điện thoại, lựa chọn Resolution vừa phải thôi, nó có rất nhiều chủng loại. Nhưng lưu ý là khi tạo máy ảo nó chiếm như máy thật trong Laptop. Nên Tui đề nghị các bạn chọn Nexus 4 (4.7″) cho nó nhẹ nhàng.
Sau đó nhấn Next, Android sẽ yêu cầu chọn System Image (là lựa chọn phiên bản Android SDK, OS version):
ở màn hình trên, Bạn thấy của Tui có version thì có chữ Download, có cái thì không. Cái nào không có chữ Download tức là đã tải thành công rồi, Cái nào có chữ Download kế bên tức là chưa tải gì cả. Của bạn thì thường là toàn bộ 100% có chữ Download kế bên do bạn chưa cài bao giờ.
Bạn chọn phiên bản rồi nhấn Download nhé, phiên bản nào cũng được miễn là >=26 (Cái Project HelloWorld đình đám của bạn chọn min là 26, và cũng là đề nghị của Google). Phần mềm của bạn chỉ có thể chạy được với các điện thoại có API >=26 trở lên.
Giả sử bây giờ Tui muốn dùng bản R, Tui sẽ bấm vào chữ Download:
Khi nhấn Download thì có ra màn hình SDK QuickFix installation:
Bạn thấy dung lượng khoảng hơn 1 GB. Ráng ngồi đợi cho nó tải xong nhé, khi nào xong ta sẽ thấy màn hình như dưới đây:
Bạn bấm Finish nhé, lúc này nó quay lại màn hình chọn System Image, và rõ ràng chữ Download thần thánh kế bên R đã ra đi không kèn không trống. Tới đây ta bắt đầu làm điện thoại ảo được rồi:
Ta chọn R -> rồi bấm Next.
AVD Name: Là tên của máy ảo, thích đặt tên gì cũng được.
Sau đó nhấn FINISH luôn nha
Lưu ý: Mới học thì đừng có tỏ vẻ nguy hiểm chỗ này, bên trong nó còn nhiều cấu hình khác như là RAM, SD card…. bằng cách nhấn vào Show Advanced Settings:
Các thông số ở đây nó y chang như điện thoại thật, bạn mà táy máy nâng nó lên thì ổ cứng của bạn sẽ bị sài hết nha.
Do đó cứ để mặc định ban đầu, nhấn FINISH luôn nghe không. Sau khi bấm FINISH, tên máy ảo này sẽ xuất hiện vào danh sách dưới đây:
Mỗi một máy ảo nó có các nút: Chạy, Sửa….:
Ta bấm vào biểu tượng hình Tam giác để chạy điện thoại nhé (lần đầu chạy hơi lâu nhé, ráng chờ):
Trước mặt chúng ta là 1 điện thoại giả lập nó y chang như điện thoại thật nha: Nó có thể nhắn tin, gọi điện thoại, kiểm tra Sensor, Google map…
Như vậy các bạn đã tạo được Điện thoại giả lập thành công, bài học sauTui sẽ trình bày sơ lược cách sử dụng máy ảo trước khi chúng ta chạy phần mềm “HelloWorld” thần thánh lên nó.
Trong Node, biến Environment là một biến global, thường được sử dụng để chỉ định process nào muốn chạy. Ví dụ, khi chạy một ứng dụng web, ta sẽ có các biến Environment sau:
Port
Database connection string
Nếu đã từng làm việc với .Net, chắc sẽ biết tới file web.config. Biến Environment làm việc i như các thiết đặt trong web.config
Set giá trị bằng terminal
Thí dụ ta set giá trị của PORT
PORT=6060 NODE_ENV=production webpack
Giờ lúc code, ta gọi cái biến này ra bằng cách
var port = process.env.PORT
Không phải lúc nào set giá trị của biến env bằng terminal, ví dụ connection string thì không ai đưa vào bằng terminal
Webhook là gì? – Về mặt cơ bản, Webhook là một tính năng cho phép website tự động thông báo và gửi dữ liệu thời gian thực đến các hệ thống khi có một sự kiện nào đó phát sinh trên website (ví dụ như khánh hàng đăng ký, điền form, mua hàng, hay gửi email) Webhook sẽ giúp hệ thống của bạn chủ động hơn trong việc vận hành cũng như trao đổi thông tin.
Webhook là một công nghệ rất tiện dụng trong việc triển khai các phản ứng sự kiện (event) trên website của bạn. Webhook cung cấp một giải pháp giúp ứng dụng server-side thông báo cho ứng dụng phía client-side khi có sự kiện phát sinh đã xảy ra trên máy chủ (event reaction). Cũng chính vì vậy, ứng dụng client-side sẽ không cần phải liên tục hỏi hoặc check với ứng dụng server-side.
Nhiều người cũng thường gọi Webhook là “Reverse APIs”. Thông thường đối với các API, ứng dụng client-side sẽ gọi ứng dụng server-side. Tuy nhiên khi có webhook, phía server-side sẽ gọi webhook (end-point URL được cung cấp bởi ứng dụng client-side), ví dụ: ứng dụng server-side gọi ứng dụng client-side.
Một ví dụ khác: Bạn đã sử dụng API để tạo một ứng dụng theo dõi thời điểm khách hàng đến nhà hàng của bạn. Nhờ nó mà bạn có thể chào hỏi khách hàng bằng đúng tên của họ và cung cấp đồ uống miễn phí khi họ nhận bàn nếu bạn muốn.
Những gì Webhook làm là thông báo cho bạn bất cứ khi nào có sự kiện gì diễn ra, vì vậy bạn có thể vận hành bất kỳ quy trình nào mà bạn đã có trong ứng dụng của mình sau khi sự kiện này được kích hoạt. Sau đó, dữ liệu được gửi qua web từ ứng dụng nơi sự kiện xảy ra ban đầu, đến ứng dụng nhận xử lý dữ liệu.
Webhook thường được các lập trình viên sử dụng để cập nhất các event theo thời gian thực một cách tiết kiệm tài nguyên nhất có thể. Cũng chình vì vậy mà Webhook được sử dụng trong trường hợp này.
Ngoài ra Webhook còn đường dùng qua API là khi API của bạn không tốt lắm hoặc thậm chí là không có API để bắt đầu. Vì vậy thông qua Webhook, bạn có thể tạo một giải pháp cung cấp dữ liệu mà ứng dụng của bạn cần để hoạt động ngay một cách trơn tru nhất.
Có một lưu ý nhỏ thế này, tuy Webhook khá linh động nhưng nếu nó không được sử dụng thường xuyên để call dữ liệu (vì nó chỉ hoạt động khi có dữ liệu hoặc event mới trên hệ thống), nên dẫn đến khả năng sẽ không thể lấy được các bản cập nhật mới nhất nếu hệ thống dừng hoạt động vì một lý do bất chợt nào đó.
Những ví dụ về Webhook
Webhook dễ tạo hơn một API thông thường rất nhiều, người dùng nó cũng không cần quan tâm quá nhiều tới việc nâng cấp cơ sở hạ tầng về sau. Về có bản Webhook chỉ như là một POST Request được gửi đến một URl cụ thể. Thông thường Webhook sẽ POST data theo 2 cách căn bản là: JSON hoặc XML. Bên phía provider sẽ cho bạn biết nội dung hoặc có thể tối ưu lại thêm cho nội dung của các API được cung cấp này.
Giả sử bạn tạo một form và submit nó trong code, tương tự như bạn tạo POST request. Bạn sẽ dùng HTTP library ví dụ như là Guzzle chẳng hạn. Phía đầu nhận bạn sẽ thiết lập một URL để nhận POST request. Ví dụ trong Laravel bạn sẽ dùng một thứ giống như thế này.
Phía end-point đầu nhận của bạn sẽ có thể tiếp nhận object này và sau đó tiến hành process bất cứ thứ gì mà bạn muốn.
Một ví dụ khác ví dụ khi bạn mua hàng trên một trang thương mại điện tử chẳng hạn (client-side-application), thẻ tín dụng của bạn ghi nhận có sự thay đổi (thanh toán mua hàng chẳng hạn). Hành động này sẽ tạo ra hành động confirm mua hàng phía client-side, và gửi cho họ thông báo confirm hành động mua hàng.
Một URL sẽ được tạo ra ở phía server của bạn và process một cái POST request. Sau đó bạn cung cấp một URL cho Webhook service provider.
Bước action app URL
muahangonline.com/data/98712
Tiếp đến URL được nạp thêm nhiều Data, bao gồm tên khách hàng, ngày mua, số lượng mua, giá trị đơn hàng. Nó được chuyển thành dạng serialized format.
Bước Serialized format
Customer=Phương&value=300.000&item=bagfashion
Để tạo ra GET request, cả URL và serialized format phải được kết lại To generate the GET request, both the URL and the serialized format are combined. Một dấu “?” được add ngay vào phía cuối của dữ liệu URL của APP
Để webhook hoạt động đúng, GET request cần được bổ sung vào thanh browser address bar. Bạn có thể đơn giản tạo các webhook trong Zapier và link các applications liên quan vào. Khi một update xuất hiện, toàn bộ sẽ phản ứng dựa trên các hành động cần thiết. Nó cũng đơn giản như việc bạn connect Google calendar với Slack, khi có event mới trên google calendar, bạn sẽ được nhận slack notification.
Một lần nữa nhắc lại, các lệnh được gửi từ nơi này đến một nơi khác thông qua HTTP. Webhook gọi nó là “user-defined HTTP callbackx” bởi vì nó thường sẽ là nơi trigger các evet. Hành động mà application có thể gửi callback message để trigger application và khiến cho application hiểu là data đã được nhận hay chưa. nên không nhận được sẽ show “Error 404”. Nói tóm lại, bạn có thể setup nhiều loại webhook khác nhau cho nhiều loại tương tác khác nhau trên hệ thống của mình
Một số ví dụ thực tiễn và trực quan khác về Webhook
MailChimp: Họ dùng Webhook cho một số event quan trọng như subscribing, unsubscribing, they đổi thông tin profile. Điều này khá hữu dụng nếu bạn dùng MailChimp để signup cho người dùng từ website của bạn cho newsletter.
Sendgrid: Dùng webhook để xác định những email transactional của bạn có được deliver đúng hay chưa, có được mở chưa, mở có đúng hay chưa. Đây cũng là một tính năng quan trọng nếu bạn muốn gửi một số email trọng yếu của mình đến người dùng. Vì nếu họ không nhận được email, bạn sẽ có thể đưa ra giải pháp khác để khắc phục.
Stripe: Tương tự như trên, Stripe cũng cho phép trigger rất nhiều loại event khác nhau. Ví dụ như thanh toán có thông qua hay không, ngày tháng có chính xác không để hỗ trợ cho việc renew subscription được chính xác hơn.
Tổng kết bài viết webhook là gì?
Webhook là một phần quan trọng của web và ngày càng trở nên phổ biến hơn. Chúng cho phép các ứng dụng của bạn truyền dữ liệu ngay lập tức và liền mạch cho nhau. Cách dễ nhất để hiểu webhooks là tự bản thân trải nghiệm nó. Bạn có thể tạo một vài kết nối webhook giữa các ứng dụng của mình để cảm nhận nó và bạn sẽ nhanh chóng hiểu nó rõ hơn.
Có 2 điều quan trọng cần lưu ý bạn nếu sử dụng webhook là gì?
Webhook cung cấp dữ liệu cho application của bạn và có thể ngừng quan tâm sau khi yêu cầu: điều này đồng nghĩa với việc nếu ứng dụng của bạn bị lỗi thì dữ liệu có thể bị mất. Hơn thế nữa, nếu ứng dụng của bạn xử lý yêu cầu mà vẫn bị lỗi thì có thể dữ liệu bị trùng lặp trong ứng dụng của bạn. Vì vây, bạn cần hiểu rõ cách mà nhà cung cấp webhook của bạn xử lý các phản hồi để bạn có thể chuẩn bị cho trường hợp lỗi xảy ra trong ứng dụng.
Webhook có thể thực hiện rất nhiều yêu cầu: Nếu như nhà cung cấp có nhiều event cần được thực thi, hay nhiều yêu cầu liên tục gửi đến khách hàng có thể dẫn đến DDoSing
Bài viết được sự cho phép của tác giả Trần Anh Tuấn
Hello xin chào các bạn, lâu lắm rồi mình chưa viết bài mới cho blog, vì lâu nay mình đang suy nghĩ tìm chủ đề mới để viết cho blog để giúp các bạn học hỏi, cải thiện trình độ và hôm nay mình đã tìm ra một chuyên mục mới cho blog của mình đó chính là Javascript thực chiến nghĩa là thay vì viết những bài về kiến thức cơ bản thì mình sẽ làm các bài như là hướng dẫn code chức năng tab, autocomplete, scroll fixed, toggle menu, slider…
Là những vấn đề khi đi làm mà các bạn sẽ hay gặp phải, làm sao để phân tích vấn đề, đưa ra giải pháp và để code nó thì series này mình sẽ cố gắng chia sẻ nhiều cho các bạn luôn. Và bài đầu tiên của series này chính là hướng dẫn code chức năng đổi màu nền ngẫu nhiên trước nhé.
Cho một danh sách màu sắc bất kỳ, khi nhấn vào một nút button ở ngoài giao diện thì màu nền của trang web sẽ đổi ngẫu nhiên(random) trong danh sách màu sắc đã cho từ trước.
Giao diện HTML CSS
Về giao diện thì chúng ta chỉ cần tạo HTML đơn giản mà thôi với một button có class button-random và CSS thêm một chút như sau:
<button class=“button-random”>Change</button>
body {
width:100%;
height:100vh;
background-color:#1a1c28;
transition:background-color0.2slinear;
}
.button-random {
color:white;
margin:2remauto;
padding:1.5rem3rem;
text-align:center;
display:block;
text-transform:uppercase;
font-family:inherit;
background-color:#ff7870;
border:0;
border-radius:4px;
cursor:pointer;
outline:none;
}
Và ta sẽ có kết quả đơn giản như này:
Javascript Code
Việc đầu tiên chúng ta cần làm đó chính là khai báo các biến cần sử dụng, ở đây mình đặt một biến có tên là colors là một mảng sẽ chứa danh sách các màu bất kỳ như sau:
constcolors=[
“#00aefd”,
“#ffa400”,
“#07a787”,
“#ff7870”,
“black”,
“pink”,
“yellow”,
“#e74c3c”,
“#2979ff”,
];
Tiếp đến mình khai báo thêm 1 biến để chứa cái button-random để chúng ta thêm sự kiện nhấn vào cho nó sau này với phương thức document.querySelector để lấy ra một phần tử trong DOM(Document Object Model).
Phần khai báo đã xong, bây giờ chúng ta sẽ thêm sự kiện nhấn vào nút button này bằng phương thức addEventListener và sự kiện truyền vào sẽ là click, khi nhấn vào nút thì lúc này chúng ta cần có giải pháp để lấy màu ngẫu nhiên ra.
Để lấy giá trị trong mảng thì chúng ta sẽ truy xuất đến vị trí index của phần tử trong mảng ví dụ colors[0] thì sẽ lấy ra giá trị đầu tiên là #00aefd trong trường hợp này, thì để lấy ngẫu nhiên thì chúng ta sẽ sử dụng hàm Math.random(), hàm này sẽ trả về kết quả từ 0 đến 1 như 0,2 0,7… nhưng cái chúng ta muốn chính là lấy từ 0 cho đến chiều dài của mảng cho nên lúc này để có kết quả chính xác thì code của chúng ta phải là Math.random() * colors.length
Tuy nhiên con số khi ra đôi khi sẽ là 7,2 mà trong mảng nếu để colors[7,2] thì sẽ không đúng cho nên chúng ta cần làm tròn nó xuống bằng cách thêm một hàm khác bọc lại giá trị ở trên chính là Math.floor() sẽ làm tròn xuống ví dụ 7,2 sẽ thành 7, lúc này trở đi ta có thể dùng một biến có tên là randomColor để lấy ra màu ngẫu nhiên bằng đoạn code mà chúng ta phân tích nãy giờ như sau:
Qua bài viết này, mình hi vọng sẽ giúp ích được cho các bạn phần nào trong việc học tập và thực hành với Javascript nhé, cũng như học thêm được cách phân tích vấn đề, các bước để làm ra kết quả như mong muốn, học cách lấy giá trị ngẫu nhiên trong một mảng với các hàm Math, ôn lại sự kiện click, gán giá trị vào style của DOM… Cuối cùng mình chúc các bạn một ngày an lành và vui vẻ. Nếu bài viết mình có gì sai thì các bạn góp ý giúp mình nhé.
Bài viết được sự cho phép của tác giả Trần Khôi Nguyên Hoàng
Mở bài
Bác Gates đã bảo rằng bác luôn muốn chọn những người lười biếng vì họ sẽ tìm ra cách thực hiện việc đó một cách đơn giản hơn.
Hơn nữa, đôi khi có một số công việc nhàm chán phải lặp đi lặp lại nhiều lần, trong một ngày. Với một developer thì tại sao không tìm một cách nào đó nhàn hơn để làm?
Hôm nay mình sẽ giới thiệu với các bạn cách để tự động hóa một số công việc bằng NodeJS và Heroku, hoàn toàn miễn phí.
Sau đó, các bạn có thể áp dụng vào chính công việc hiện tại của các bạn như gửi mail, tự động chúc mừng sinh nhật trên Facebook, và hàng tá việc khác nữa.
Để áp dụng, mình sẽ hướng dẫn các bạn viết một cái script vui vui nhằm áp dụng thử tự động hóa một số việc đơn giản. Mình sẽ viết một cái script lấy bài từ Subreddit r/listentothis và post sang Facebook Page bằng NodeJS mỗi giờ một lần.
Series gồm hai phần:
Viết script
Tự động hóa bằng Heroku
Code nào
Đầu tiên là mình sẽ viết một script để nó tự động lấy bài bên Subreddit và post sang Facebook Page. Các bước cụ thể sẽ như sau:
Ở đây mình sẽ sử dụng NodeJS cùng một số package như snoowrap cho Reddit API và node-fetch để post bài lên Page. Ngoài ra dùng thêm dotenv để config các biến environment nữa thôi. Easy
npm init -y
touch index.js
npm i snoowrap node-fetch dotenv
Bash
Config Đít Đỏ
Để Config Đít Đỏ thì mình sử dụng Snoowrap package. Setup gồm hai bước là tạo Reddit App và tạo Token vĩnh viễn.
Sau khi tạo xong thì lưu lại Client ID và Client Secret lại.
Tạo Token vĩnh viễn
Tạo Token vĩnh viễn thì các bạn tiếp tục vào https://not-an-aardvark.github.io/reddit-oauth-helper/. Sau đó điền Client Secret và Client ID vào. Nhớ tick vào Permanent sau đó tạo Token. Kéo xuống dưới nó sẽ hiện Token. Lưu tiếp 2 cái Token đó lại là xong.
Lấy random post từ Subreddit
Đến đây mình bắt đầu vào file index.js để bắt đầu Code.
const fetch =require("node-fetch");const snoowrap =require("snoowrap");require("dotenv").config();(async()=>{try{// Config Snoowrapconst r =newsnoowrap({userAgent:"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",clientId: process.env.REDDIT_CLIENT_ID,clientSecret: process.env.REDDIT_CLIENT_SECRET,refreshToken: process.env.REDDIT_REFRESH_TOKEN});// Get Sub Redditconst subReddit = r.getSubreddit("listentothis");// Get Random postconst randomPost =await subReddit.getRandomSubmission();console.log(randomPost);}catch(error){console.error(error);}})();
JavaScript
Kết quả sẽ trả về Object một bài post random từ Subreddit r/listentothis. Ở đây mình sẽ lấy demo 3 giá trị thôi: Title, Author và Url của bài hát đó.
Tiếp theo là các bạn phải tạo Page, sau đó tạo App trên Facebook Developer. Và lấy token vĩnh viễn. Các bạn chưa biết cách lấy Token vĩnh viễn thì xem ở đây nhé. Đoạn này nhiều bài hướng dẫn nên mình lười viết lại quá.
// Post Statusconst access_token = process.env.FACEBOOK_ACCESS_TOKEN;const messageData ={url: randomPost.url,author: randomPost.author.name,title: randomPost.title
};const messageTemplate =`Listen and enjoy to this song ${messageData.title} | Credit: ${messageData.author}`;const url =`https://graph.facebook.com/v5.0/101580544646661/feed?message=${messageTemplate}&link=${messageData.url}&access_token=${access_token}`;const postStatus =awaitfetch(url,{method:"POST"});const response =await postStatus.json();console.log(response);
JavaScript
Test thử
Bật Tơ Mi Nồ lên và gõ node index.js để test. Nếu kết quả như sau là chính xác
{ id: '101580544646661_102170374587678' }
JSON
Kết luận
Đến đây là coi như đã xong cái script đơn giản, tự động lấy bài bên Reddit để post qua Facebook Page rồi nhé. Các bạn có thể xem thử kết quả ở Page http://fb.com/listenthisawesomesong của mình.
Source Code của script này mình ở đây https://github.com/nguyen47/listen-to-this
Phần sau mình sẽ giới thiệu cách để tự động hóa việc này bằng Heroku. Đơn giản và không tốn chi phí gì cả.
Hello anh em!. Do mùa dịch nên lụm được một kèo làm project với Client bên Canada về AWS Lambda, nên tiện viết luôn bài về Functions as a Service (FaaS).
Bài viết không có gì hơn ngoài mục đích cung cấp cho anh em một cái nhìn tương đối hoàn chỉnh về Faas, sau này còn có thêm về Platform-as-a-Service (PaaS). So sánh điểm mạnh yếu, khác nhau giữa hai kiến trúc này.
Mong anh em chú ý đón đọc (rang ráng sao đó đọc cho hết bài). Lụm được kèo thơm – tiện đây nói với anh em là Tiếng Anh đối với dev như anh em mình quan trọng lắm luôn
Functions as a service là gì?
Function as a service (FaaS) is a serverless way to execute modular pieces of code on the edge. FaaS lets developers write and update a piece of code on the fly, which can then be executed in response to an event.
Function as a Service (FaaS) là kiến trúc serverless, thực thi các phần module của code bên phía server. FaaS giúp lập trình viên viết và cập nhận các phần của code nhanh chóng, sau đó thực thi và trả vè kết quả.
Biết về FaaS thì nên vọc vạch cho biết về Amazon Lambda luôn nha.
Đọc hơi khó hiểu, nhưng bình thường, nếu không biết về kiến trúc FaaS. Chỉ đơn giản cần hình dung là:
With FaaS, the physical hardware, virtual machine operating system, and web server software management are all handled automatically by your cloud service provider.
Với FaaS, các thiết bị phần cứng, hệ thống máy ảo và web server đều được handle một cách tự động bởi cloud service được cung cấp
Function chỉ làm một việc
Với triết lý lập trình hàm (Function do only one thing), khi làm việc với kiến trúc Functions as a service, chỉ nên để function làm một việc duy nhất
Make your code scope limited, efficient, and lightweight so functions load and execute quickly.
Làm cho source code bớt dài dòng, hiệu quả và nhẹ để các chức năng tải và thực thi nhanh chóng.
Đừng gọi function này trong function khác
Điểm mạnh nhất của FaaS là nó độc lập các function, nếu function chỉ thực thi một nhiệm vụ duy nhất. FaaS sẽ làm rất tốt công việc của nó được giao. Tuy nhiên, nếu gọi các function lồng nhau, rất dễ xảy ra vấn đề về performance.
Too many functions will increase your costs and remove the value of the isolation of your functions.
Quá nhiều functions sẽ làm răng giá phải trả và loại bỏ đi giá trị của sự độc lập giữa các function.
Sử dụng quá nhiều libraries
Một số services hướng FaaS hỗ trợ tận răng cho developer các function, libraries. Tuy nhiên, không phải vì vậy mà ta lạm dụng.
Using too many libraries can slow functions down and make them harder to scale.
Sử dụng quá nhiều libraries sẽ làm chậm các functions và khiến chúng khó để scale.
Ưu điểm khi sử dụng Faas
Tốc độ – Improved developer velocity
Rõ ràng mà nói, thay vì ngồi lò mò lo code, rồi build, rồi run. Chưa hết, nếu lên server test thì còn deploy nữa. Thật là quá nhiều công đoạn, quá trình nhiêu khê.
Với Functions as a service, dev giờ chỉ lo code. Nhanh hơn rất nhiều!
With FaaS, developers can spend more time writing application logic and less time worrying about servers and deploys. This typically means a much faster development turnaround.
Với FaaS, lập trình viên có thể có thểm thời gian để viết về logic của ứng dụng, bớt thời gian lo lắng về servers và deploys. Điều đó cũng đồng nghĩa với việc development nhanh hơn.
Khả năng mở rộng – Scability
Thay vì phải lo lắng phía server handle ra sao cho hàng triệu request. Với Functions as a service, dev giờ chỉ focus vào thực thi function, còn scale ra sao đã có phía server lo.
Developers don’t have to worry about creating contingencies for high traffic or heavy use. The serverless provider will handle all of the scaling concerns.
Dev không còn phải lo vấn đề về quá tải khi traffic cao/ Server sẽ cung cấp và handle tất cả các vấn đề liên quan với scaling.
Giá cả – Cost efficiency
Thay vì phải trả tiền hằng tháng cho một service to bự. Hầu hết các nhà cung cấp đều chỉ tính tiền khi người dùng thực sự sử dụng
Clients only pay for as much computation time as they use, and do not need to waste money over-provisioning cloud resources.
Khách hàng chỉ trả tiền cho thời gian mà họ sử dụng, không phải phung phí tiền cho các tài nguyên cloud khác.
Nhược điểm
Sinh ra với kha khá ưu điểm hơn người, tuy nhiên cũng có những nhược điểm cần biết về Functions as a Service (FaaS) để mà tránh.
Thứ nhất, sử dụng FaaS sẽ gây khó khăn cho việc code. Khởi tạo environtment để test hoặc investigation bug ở môi trường local là vô cùng khó khăn.
It can be very difficult to incorporate FaaS code into a local testing environment, making thorough testing of an application a more intensive task.
Sẽ là rất khó để tích hợp code của FaaS vào môi trường kiểm thử ở local. Việc này vô hình chung biến kiểm thử cho ứng dụng trở thành một task chuyên sâu hơn
Nhiều thách thức được nhà tuyển dụng đặt ra trong buổi phòng vấn nhằm đánh giá năng lực, mục tiêu phát triển và khai thác cá tính nghề nghiệp trong bạn. Chắc hẳn câu hỏi: “Mục tiêu của bạn trong 5 năm hay 10 năm tới là gì?” không còn quá xa lạ với bạn. Vậy bạn sẽ giải quyết thách thức này ra sao?
Cùng TopDev đi vào phần 1 của vấn đề này – Những vấn đề xoay quanh việc nhận ra giá trị bản thân và nắm bắt mong muốn từ nhà tuyển dụng nhé!
Nhìn nhận về tâm lý chung, các ứng viên dường như rất e ngại về một đáp án cho câu hỏi tuyển dụng. Đơn giản, vì họ lo lắng rằng mục tiêu phát triển của bản thân không đáp ứng với những gì nhà tuyển dụng mong muốn. Bạn khó có thể đánh giá được chính xác bạn là ai, sẽ ra sao sau 5 năm nữa. Đó là lý do mà một mô tả quá cụ thể cho đáp án hiện tại chưa thể nói lên điều gì.
Đừng áp lực! Vì không có một đáp án nào hoàn hảo cho câu hỏi này
Trên thực tế, nhà tuyển dụng có thể đặt ra câu hỏi hoặc không? Và khi họ cố tình đặt ra chúng thì chắc chắn phải có mục đích.
Họ không quá kỳ vọng rằng bạn có thể lên các kế hoạch chi tiết cho cuộc sống và hành trình sự nghiệp. Thế điều gì ở bạn mà họ muốn tìm kiếm? Nhà tuyển dụng rất chú trọng đến việc các ứng viên theo đuổi những giá trị gì. Từ các giá trị, mỗi ứng viên có thể liên kết các kế hoạch. Đó chính là cơ sở nền tảng để thiêt lập các nhiệm vụ cụ thể. Qua đó, giúp họ từng bước chạm gần hơn với các mục tiêu.
Bạn hãy xem đây là cơ hội để nhà tuyển dụng thấy được đâu là các giá trị thực mà bạn có thể tạo ra. Đồng thời, họ cũng muốn đánh giá các chỉ số khác về sự đam mê, sự nỗ lực,.. thông qua cách thức mà bạn trải nghiệm dựa trên những giá trị đó.
Thấu hiểu những mong muốn từ nhà tuyển dụng – “Dễ” mà “Khó”
Những mong muốn từ nhà tuyển dụng từ ứng viên rất khó để xác định. Từng vị trí với những đòi hỏi về chuyên môn khác nhau sẽ tương ứng với các tiêu chí riêng biệt.
Đặc biệt hơn, khi mỗi cá nhân đang sống và làm việc trong một nhịp sống quá ganh đua, họ quên đi cái gọi là giá trị mà bản thân họ đang sở hữu.
Chung quy lại, nhà tuyển dụng họ chỉ muốn biết được bạn đang làm việc gì cái gì? Bạn thử sức cho các vị trí ấy với mong muốn tạo ra giá trị gì cho bản thân? Bạn muốn trở thành một người như thế nào?
Hiểu được mong muốn của nhà tuyển dụng vừa dễ lại vừa khó. Tuy nhiên, việc nắm bắt tốt các mong muốn dù chỉ là những hình dung nhỏ, bạn đã đủ sức tạo ra được sự khác biệt trong vô số ứng viên. Thế nên, điều quan trọng là hãy tìm kiếm bạn đang theo đuổi điều gì. Và làm thế nào để bạn có được nó. Sự quyết tâm, hay tính nhẫn nại? Hãy chia sẻ chúng với nhà tuyển dụng vì họ thật sự cần biết điều đó từ bạn.
Giữ các giá trị và kết nối chúng để tạo dấu ấn
Có thể sẽ khó khăn ghi bạn tự nhìn nhận lại các giá trị bản thân. Tuy vậy hãy cố gắng nhận ra nó. Bạn cần phải giữ chúng trong một trục định hướng chung. Hơn hết, bạn cần tạo ra cơ hội để kết nối các giá trị.
Thực tế cho thấy, cách sống của chúng ta ít nhiều đã làm giảm sự liên kết về các giá trị. Bạn đã mất quá nhiều thời gian để theo đuổi các mục tiêu chưa phù hợp, không phải sao?
Đối với gười trẻ thì lý do của họ rất đa dạng. Bạn đã từng nghĩ về các lý do đó chưa? Tìm một công việc để học hỏi, trải nghiệm? Có người xem nó là bước đầu trong hành trình chinh phục sự nghiệp. Trong khi đó, có người xem đó như một lần thử sức để đánh giá mức độ phù hợp. Họ nghĩ rằng tuổi trẻ còn dài, cứ đi và đích đến hoàn hảo nhất sẽ được tìm thấy.
Nếu bạn cứ trải nghiệm vì cho rằng bạn có năng lực thì điều đó hoàn toàn sai lầm. Bạn chưa tận dụng hợp lý khả năng, bạn chỉ đang lãng phí tài năng của mình. Hãy đặt ra câu hỏi: “Tai sao bạn lại lựa chọn làm công việc này? Động lực nào khiến bạn muốn thực hiện nó? Đừng quên mất mục đích bạn mong muốn là gì! Điều đó sẽ tao ra sự hoài nghi. Và tất nhiên, hành trình trải nghiệm và thực hiện mục tiêu sẽ sớm bị thủ tiêu. 5 năm hay 10 năm lúc này chỉ còn là một câu nói vui mà thôi.
Lời kết
Thế là cách giúp bạn tự nhìn nhận về giá trị bản thân và hiểu được mong muốn từ nhà tuyển dụng đã được giải đáp. Mục tiêu phát triển bản thân của bạn có được thăng hoa hay không phụ thuộc lớn vào bước đi đầu tiên này. Ở phần tiếp theo, TopDev sẽ có những phân tích sâu sắc hơn về cách thức trả lời thách thức từ nhà tuyển dụng: Mục tiêu nào bạn đặt ra vào 5 năm tới?
Cách nhanh nhất để lên trình Front end là tự triển những project thật. Bạn có thể xem tutorials, hay tham gia rất nhiều khóa học, nhưng nếu không tự ứng dụng và thực hành thì sẽ rất khó để bạn thực sự tiếp thu những kỹ năng cần thiết cho những projects thực tế.
Những project từ client thì sẽ không có hướng dẫn từ A đến Z, nếu có thì họ cũng chẳng cần bạn làm gì. Với project được giao, bạn phải tự thân vận động từ solution, thực hiện từng bước, thậm chí hack quá trình để về đích.
Vì vậy cách tốt nhất để luyện skill là bắt tay tự làm những project front-end và tự rút ra bài học kinh nghiệm cá nhân luôn một thể. Chưa cần khách hàng vào thời điểm này khi tự bạn có thể build project cho riêng mình.
Chọn Project cá nhân như thế nào?
Xác định level kỹ năng
Khoan hãy chọn những project quá nâng cao so với trình hiện tại, nhất là nếu bạn dễ nản khi gặp khó khăn. Nhưng cũng đừng quên mục tiêu đặt ra là để master front-end, cho nên hãy chọn một project cao hơn so với skill level hiện tại, mà vẫn khả thi.
Ví dụ, bạn vừa hoàn thành HTML và CSS, thì đã đến lúc tìm hiểu thêm JavaScript.
Xử lý problem cá nhân hay bài toán mà bạn quan tâm
Bạn sẽ hào hứng và “dính” với project hơn nếu có problem liên quan đến cuộc sống xung quanh hay nó có thể đáp ứng mong muốn nào đó của riêng bạn.
Có thể nhiều lúc bạn mất kiểm soát về thời gian khi lướt Facebook quá nhiều, hoặc bạn đang muốn có một cái web mà có thể tự tạo Youtube thumbnails. Nói chung là bạn hãy c nhắc một vấn đề cá nhân mà công nghệ có thể nhúng tay vào và bắt đầu từ đó, những gợi ý trong bài này chỉ là khởi điểm cơ bản thôi, nếu bạn tự thêm những tính năng độc lạ thì càng đỉnh.
Một cách hay để tìm hiểu một trang web được dựng như thế nào và một số cách bài trí cơ bản như cấu trúc trang, màu sắc, font chữ, media, table, vân vân. Đào càng chi tiết có thể để dựng bản y hệt từ phiên bản gốc. Có thể chọn website nào tùy thích, hạn chế nhìn source code để có cái nhìn tổng thể nhất.
Clone Google là một trong những bài tập của Thinkful – một tổ chức giáo dục cung cấp các khóa học technology bao gồm web development bootcamp, giao cho học viên của họ.
Bạn cũng có thể bắt chước bài tập này để clone trang của app Karma WiFi, của Kyle Koshki, một trong những giảng viên tại Thinkful, và sử dụng HTML và CSS.
Ưu điểm khi clone một website là có thể tùy ý chọn độ phức tạp của trang web đó. Mới bắt đầu thì có thể chọn web nào đơn giản mà chỉ cần mỗi HTML và CSS. Nâng cấp hơn thì có thể thêm JavaScript và React.
JavaScript là ngôn ngữ lập trình cho phép tạo trang web tương tác. Sử dụng ngôn ngữ này bạn có thể tạo những element responsive như là menu, video, hiệu ứng animation, interactive maps và thậm chí game in-browser. Vậy tại sao đầu tiên phải build quiz?
Không chỉ vì game thú vị, quiz đang dần trở nên phổ biến như các công cụ content marketing. Bạn đã bắt gặp những thứ này chưa?
Quizz là công cụ marketing khá hiệu quả vì chúng có tính năng tương tác. Theo một khảo sát của Content Marketing Institute, 81% marketer cho rằng interactive content – bất kỳ nội dung nào yêu cầu người dùng phải tham gia – thu hút chú ý hiệu quả hơn hẳn content tĩnh. Vì lý do này, quiz được dùng cho các mục đích marketing khác nhau. Những câu quiz đơn giản, như hình bên trái, được dùng để đẩy traffic của web.
Tại sao bạn cần biết những chuyên này? Bởi vì công việc của bạn không phải chỉ tạo nên sản phẩm đẹp, mà còn phải tạo những tính năng thân thiện với user – user-friendly và khiến web của khách hàng hoạt động hiệu quả, đạt mục đích sale và marketing của họ nữa.
Barcode và QR đang dần thay đổi cách thức mua sắm của người dùng. Với smartphone, khách hàng có thể scan sản phẩm và có được hàng tá thông tin về sản phẩm như giá cả hay nơi bán. Không cần phải gõ những dòng code dài ngoằng lên web như activation code hay số hiệu model, khiến cho trải nghiệm mua sắm đơn giản và dễ dàng dho7n.
Trái với những gì mọi người nghĩ, bạn không cần hẳn một cái app native để scan QR codes. Website chạy trên thiết bị thông minh có camera có thể làm được chuyện đó. Trang này sẽ hướng dẫn bạn từng bước một tạo máy quét QR code của riêng mình.
Bạn sẽ dùng HTML và JavaScript, nhưng phần quan trọng nhất là sử dụng thư viện JS mà có thể biên dịch QR code. Không cần phải tạo một thư viện từ đầu vì đã có sẵn khá nhiều.
Build app front-end thời tiết
Luyện skill: Angular 8
Angular là một trong ba frameworks front-end phổ biến nhất bên cạnh React và Vue.js. Nó thường được dùng để build app form-based (app mà phải sign up để tạo account) nhưng cũng có thể dùng để build game và thậm chí những app có yếu tố virtual reality (thực tế ảo).
Trên Medium có một tutorial step-by-step rất chi tiết hướng dẫn beginner cách tạp một cái app thời tiết khá đẹp mắt với Angular 8 (phiên bản mới nhất của Angular). Cái weather app đó như thế này:
Ứng dụng này có thiết kế tinh gọn và tối giản với hình minh họa bắt mắt và giao diện đơn giản. Nó còn có cả tính năng light/dark mode. Với project này bạn sẽ cảm giác như build một app responsive, hữu dụng từ đầu đến cuối. Có thể học thêm vài thứ như installNode.js và Angular CLI để test code với LightHouse.
Mặc dù tác giả của tutorial này đã thiết kế giao diện của riêng ổng, nhưng bạn vẫn có thể sáng tạo thêm styling của riêng mình. Chọn thêm animation CSS, dùng thêm logo, icon và những materials khác.
Tutorial này thích hợp với beginner nhưng vẫn cần một chút hiểu biết về Angular, và bạn có thể xem qua Angular.io.
Thiết kế và code một website portfolio front-end của riêng bạn
Với một số project, có thể bạn sẽ làm chung với web designer để quyết định phần ngoại hình của website. Mặc dù design và dev là hai khái niệm khác nhau, tuy nhiên nếu nắm bắt được web design không chỉ là bổ sung skill mà còn trang bị cho bạn khá đầy đủ nếu sau này trở thành freelancer, tự bạn có thể triển từ design tới deploy. Design và code một web portfolio của riêng mình cũng là cách tự do thể hiện đồng thời khía cạnh nghệ thuật và kỹ thuật.
Bước đầu hãy nghĩ về thông điệp và branding. Core service – service cốt lõi của bạn là gì, bạn muốn làm cho ai, tại sao họ nên chọn bạn? (Đọc thêm tại đây)
Thứ hai là tạo bản mock design để chi tiết hóa layout, màu sắc và chữ viết.
Về theme của web thì nên là tối giản hay sôi nổi, màu đơn sắc hay đậm màu? Sau đó thì thêm một số page cần thiết, như là contact page, vài bài blog, page About me, và page terms and condition (Điều khoản và Điều kiện).
Thứ ba, code đi! Dùng CSS modern để layout, thêm vài animations, chèn hình chất lượng cao. Đừng giới hạn bản thân vì bạn có thể thêm cái gì cũng được, đó là portfolio của bạn mà!
Nguồn thực hành front-end development
Cách tốt nhất để thực hành front-end development là build app thực tế, tuy nhiên cũng cần một số nơi để tìm tips, tutorials và support khi bí hay cần thêm ý kiến đóng góp.
Đây là một số bookmark phù hợp cho bạn:
freeCodeCamp.org – website với free tutorial về lý thuyết, ngôn ngữ và thực hành về web development. Họ cũng có một cộng đồng giải đáp những thắc mắc/câu hỏi.
Modern HTML & CSS From the Beginning – Đây là khóa học Udemy của Brad Traversy. Nó có những thông tin rất hữu ích, chỉ bạn mọi thứ để bắt đầu với những ngôn ngữ mới.
Frontendmentor.io – bạn có thể tìm những challenge vừa sức và nâng cấp để phát triển kỹ năng trong thời gian rảnh. Cái khó của những challenge này sẽ xếp từ “junior” đến “advanced”. Ví dụ:
Và đó là 5 dự án front-end cho bạn thử sức. Nhắc lần nữa là đây chỉ là điểm khởi đầu thôi. Bạn có thể nâng cấp lên để customize theo ý mình. Đây mới chỉ là thực hành thôi, bạn cần phải tự tay build cái gì đó để nâng trình bản thân.
TDD (Test Driven Development – Phát triển (mà trong đó việc phát triển) được lái bởi Kiểm thử) là một phương pháp tiếp cận để phát triển phần mềm. Nói cách khác, là một cách để suy nghĩ về requirement (yêu cầu) cũng như thiết kế trước khi viết các mã triển khai.
Có một mô hình giải thích khác về TDD mà trong đó coi TDD là một kỹ thuật lập trình. Tuy vậy trong bài viết này sử dụng thuật ngữ TDD theo mô hình “cách nghĩ”.
Cụ thể, “cách nghĩ” theo phương pháp TDD được diễn giải như sau:
TDD explained
RED: Quá trình phát triển bắt đầu bằng thao tác Add a Test: bổ sung một ca kiểm thử. Chưa có mã triển khai tương ứng nên ca kiểm thử này sẽ Failed. Nhưng ngay từ thời điểm đó ca kiểm thử đã có tác dụng mô tả yêu cầu cũng như thiết kế của mã triển khai.
GREEN: Mã triển khai tương ứng với ca kiểm thử được bổ sung. Mã nguồn chuyển sang giai đoạn Passed (vượt qua kiểm thử). Các mã triển khai nội bộ của chức năng có thể linh hoạt, nhưng thiết kế của mã thì tuân theo mô tả của kiểm thử.
BLUE: Mã nguồn được tái cấu trúc. Mục đích của việc tái cấu trúc là đưa mã nguồn tới trạng thái sẵn sàng để bổ sung tính năng mới. Clean Code, SOLID, Clean Architecture, KISS, Simple Design là các quy tắc và tiêu chuẩn thường được áp dụng trong bước này.
Quá trình RGB (RedGreenBlue) được lặp đi lặp lại cho đến khi các chức năng được triển khai hoàn thiện.
Về các Coding Dojo Kata
Kata (bài quyền) trong một buổi Coding Dojo được định nghĩa là những bài toán được thiết kế cho lập trình viên để luyện tập một kỹ năng trong lập trình, thông qua thực hành và lặp lại.
Các vấn đề (bài toán) được sử dụng làm kata thường đủ nhỏ (không quá khó) để giải quyết nhưng đủ thách thức để người tập không có khả năng hoàn thành trong thời gian cho phép. Đây là thiết kế của Coding Dojo nhằm giúp người tham gia tập trung vào luyện tập kỹ năng thay vì hướng tới mục đích “xong việc”.
Về Vấn đề Bowling
Vấn đề Bowling xuất phát từ luật của trò chơi Bowling.
Một ván chơi diễn ra trong 10 frame. Mỗi frame, người chơi có 2 lượt ném để hạ đổ 10 pin. Điểm của frame là tổng số pin bị hạ đổ cộng thêm điểm thưởng từ trike và spare.
Spare (các ký hiệu / trong hình trên)xảy ra khi người chơi hạ thành công cả 10 pin sau hai lượt ném. Điểm thưởng cho spare là số pin bị hạ tại lượt ném ngay sau đó.
Strike (các ký hiệu X trong hình trên) xảy ra khi người chơi hạ thành công cả 10 pin ngay từ lượt ném đầu tiên, và theo đó kết thúc frame trong một roll duy nhất. Điểm thưởng cho strike là tổng số pin bị hạ tại hai lượt ném ngay sau đó.
Người chơi đạt spare hay strike tại frame cuối cùng sẽ được ném thêm các lượt ném phụ để nhận trọn các lượt thưởng. Theo đó frame này sẽ kết thúc sau ba lượt ném.
Bài kata Bowling Game yêu cầu lập trình viên viết chương trình để tính điểm cho trò chơi này.
Mọi tính thông tin cần thiết để có được điểm của một ván chơi nằm trọn trong một ván chơi.
BowlingGame game = new BowlingGame();
Rõ ràng, điểm của một game chỉ có thể tính được tại thời điểm mà kết quả của mọi roll đều đã rõ ràng. Giả sử ta thiết kế phương thức getScore dùng để tính về điểm số của game, getScore chỉ làm được điều đó khi nó đã nhận được đầy đủ thông tin về các roll. Chẳng hạn:
BowlingGame game = new BowlingGame(); int[] rolls = // a dummy rolls array int score = game.getScore(rolls);
Cách thiết kế này không ổn, hãy để ý game.getScore(rolls), ở đây game là một thực thể (entity) nhưng lại đang được sử dụng như một service cung cấp khả năng tính điểm.
Một thiết kế tốt hơn là đặt một phương thức roll để nhận thông tin về các roll, và đặt một phương thức score được gọi khi các roll đều đã được nhập liệu hoàn chỉnh.
BowlingGame game = new BowlingGame(); repeat () { int pins = // a dummy pins; game.roll(pins); } int score = game.score();
Đây là thiết kế tối thiểu mà chúng ta có thể có thể bắt đầu phát triển chương trình.
Bắt đầu
Bài viết này dựa trên tiền đề rằng chương trình được viết bằng ngôn ngữ Java và test framework được sử dụng là JUnit.
Tạo một kiểm thử đơn vị
Với JUnit, một kiểm thử đơn vị là một class trong đó có các ca kiểm thử là những phương thức được chú thích @Test. Dưới đây là kiểm thử đơn vị cho chương trình BowlingGame với một ca kiểm thử “dummy” dùng để xác nhận rằng test framework hoạt động ổn định.
import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; public class BowlingGameTest { @Test void testAddition() { assertEquals(2, 1 + 1); } }
Thực thi kiểm thử cho kết quả
+-- JUnit Jupiter [OK] | '-- BowlingGameTest [OK]
Ca kiểm thử đầu tiên
Kiểm thử đầu tiên mô tả rằng “nếu người chơi ném trượt tất cả các roll thì điểm số sẽ là 0”.
Mô tả class chức năng
@Test void testAllMissedGame() { BowlingGame game = new BowlingGame(); }
Mã triển khai để vượt qua kiểm thử:
public class BowlingGame { }
Mô tả thao tác nhập thông tin các roll
Để mô tả một ván chơi mà tất cả các roll (tổng cộng 20) đều trượt, ở đây sử dụng một phép lặp:
@Test void testAllMissedGame() { BowlingGame game = new BowlingGame(); for (int i = 0; i < 20; i++) { game.roll(0); } }
Mã triển khai để vượt qua kiểm thử (để đơn giản, từ mục này về sau mã triển khai sẽ được viết ra mà không có chú thích gì thêm):
public class BowlingGame { public void roll(int pins) { } }
Mô tả thao tác tính điểm
@Test void testAllMissedGame() { BowlingGame game = new BowlingGame(); for (int i = 0; i < 20; i++) { game.roll(0); } int score = game.score(); }
public class BowlingGame { public void roll(int pins) { } public int score() { return -1; } }
Mô tả điểm số mong muốn
@Test void testAllMissedGame() { BowlingGame game = new BowlingGame(); for (int i = 0; i < 20; i++) { game.roll(0); } assertEquals(0, game.score()); }
public int score() { return 0; }
Tới bước này, chương trình đã có khả năng tính đúng số điểm của những ván chơi mà tất cả các roll đều trượt.
Ca kiểm thử thứ hai
Ca kiểm thử thứ hai mô tả trường hợp mà “người chơi ném đổ một số pin nào đó, nhưng không có điểm thưởng”, chúng ta chọn một trường hợp điển hình là “người chơi chỉ ném đổ một pin mỗi roll”.
Mô tả một game ăn một điểm mỗi roll
@Test void testAllMissedGame() { BowlingGame game = new BowlingGame(); for (int i = 0; i < 20; i++) { game.roll(0); } assertEquals(0, game.score()); } @Test void testAllOneGame() { BowlingGame game = new BowlingGame(); for (int i = 0; i < 20; i++) { game.roll(1); } assertEquals(20, game.score()); }
private int score; public void roll(int pins) { score += pins; } public int score() { return score; }
Trước khi triển khai chức năng tiếp theo, hãy để ý có dấu hiệu mã xấu
Trùng lắp mã khởi tạo đối tượng game
Trùng lắp mã lặp lại thao tác roll
Khử trùng lắp cho mã khởi tạo đối tượng game
Trùng lắp này có thể được khử bằng một phương thức setup mà hầu như mọi test framework đều hỗ trợ. Trong JUnit, phương thức setup được mô tả bởi chú thích @BeforeEach:
private BowlingGame game; @BeforeEach void setup() { game = new BowlingGame(); } @Test void testAllMissedGame() { for (int i = 0; i < 20; i++) { game.roll(0); } assertEquals(0, game.score()); } @Test void testAllOneGame() { for (int i = 0; i < 20; i++) { game.roll(1); } assertEquals(20, game.score()); }
Khử trùng lắp cho thao tác roll nhiều lần
Trùng lắp này có thể được khử bằng kỹ thuật tách hàm:
private BowlingGame game; @BeforeEach void setup() { game = new BowlingGame(); } @Test void testAllMissedGame() { rollMany(0, 20); assertEquals(0, game.score()); } @Test void testAllOneGame() { rollMany(1, 20); assertEquals(20, game.score()); } private void rollMany(int pins, int times) { for (int i = 0; i < times; i++) { game.roll(pins); } }
Ca kiểm thử thứ ba
Ca kiểm thử thứ ba hướng đến việc mô tả chức năng tính điểm thưởng cho spare.
Thiết kế hiện tại không thể vượt qua được kiểm thử này vì những lý do sau đây:
Score đang được tính toán “lâm thời”, trong khi để tính điểm thưởng thì cần dựa vào roll “tương lai” (hoặc “quá khứ”, tùy cách hiểu).
Để giải quyết vấn đề trên thì lịch sử kết quả của các roll cần được lưu lại, nhưng phương thức roll hiện tại không làm điều đó.
Việc tính toán điểm số cần dựa trên lịch sử, nhưng phương thức score hiện tại không làm điều đó.
Để giải quyết vấn đề trên, cần tái thiết kế mã nguồn. Để có thể tái thiết kế an toàn ta cần giữ lại hai ca kiểm thử đầu tiên. Ca kiểm thử thứ ba tạm thời chưa thể pass được và cần phải đặt sang một bên.
// @Test // void testSpare() { // ...
Lưu giữ lịch sử các roll
Phương thức roll sẽ đảm nhiệm chức năng lưu giữ lịch sử ném:
private int score = 0; private int[] rolls = new int[21]; private int currentRoll = 0; public void roll(int pins) { rolls[currentRoll++] = pins; score += pins; } public int score() { return score; }
Tính điểm số dựa trên lịch sử ném
Các mã đảm nhiệm chức năng tính điểm sẽ được bỏ ra khỏi phương thức roll. Phương thức score sẽ đảm nhiệm tính năng này, và nó thực hiện dựa theo lịch sử ném:
private int[] rolls = new int[21]; private int currentRoll = 0; public void roll(int pins) { rolls[currentRoll++] = pins; } public int score() { int score = 0; for (int i = 0; i < rolls.length; i++) { score += rolls[i]; } return score; }
Tới lúc này thì ca kiểm thử số ba có thể được gỡ comment.
Phát hiện spare
Thao tác cộng điểm thưởng cho spare bắt đầu bằng việc phát hiện ra sự kiện spare:
public int score() { // ... for (int i = 0; i < rolls.length; i++) { if (rolls[i] + rolls[i+1] == 10) // spare score += ... // score += rolls[i]; } // ... }
Giải pháp này không sử dụng được bởi thông tin i không mô tả được roll hiện tại là roll bắt đầu hay kết thúc của một frame. Thiết kế hiện tại vẫn chưa đáp ứng được ca kiểm thử số 3. Chúng ta cần một biến đếm có khả năng đại diện cho một frame, không phải một roll.
Duyệt qua các frame
Ca kiểm thử số 3 cần được comment lại một lần nữa. Phương thức score được tái cấu trúc để duyệt qua từng frame một:
public int score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[i] + rolls[i + 1]; i += 2; } return score; }
Tới lúc này thì thiết kế đã sẵn sàng để vượt qua ca kiểm thử thứ ba.
Vượt qua ca kiểm thử thứ 3
Gỡ bỏ comment cho ca kiểm thử thứ ba và bổ sung mã tính điểm thưởng cho spare:
public int score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[i] + rolls[i + 1] == 10) { // spare score += 10 + rolls[i + 2]; i += 2; } else { score += rolls[i] + rolls[i + 1]; i += 2; } } return score; }
Kiểm thử số ba đã được vượt qua, nhưng những mã xấu sau vẫn hiện diện:
Tên biến không có tính mô tả (biến i) tại mã triển khai
Sự tồn tại của comment tại mã triển khai (để giải thích cho phép so sánh magic == 10)
Sự tồn tại của comment tại mã kiểm thử (để giải thích cho cặp số magic 3-7)
Đặt lại tên biến mặc tả
Biến i của phương thức score đang mô tả vị trí bắt đầu của frame trong lịch sử các roll, có thể được đặt lại tên thành frameIndex.
Comment tại mã triển khai có thể được khử bằng cách đặt tên cho biểu thức so sánh magic rolls[frameIndex] + rolls[frameIndex + 1] == 10. Biểu thức này này mô tả dấu hiệu nhận diện một spare. Mục tiêu “đặt tên” có thể được thực hiện bằng kỹ thuật tách phương thức:
Nhờ có các tái cấu trúc trước đó, ca kiểm thử thứ tư được vượt qua rất dễ dàng. Nhưng những mã xấu sau vẫn hiện diện:
Comment tại mã triển khai
Comment tại mã kiểm thử
Khử comment tại mã triển khai
Comment tại mã triển khai hiện diện nhằm giải thích cho biểu thức magic rolls[frameIndex] == 10. Biểu thức này mô tả dấu hiệu nhận diện một strike. Dấu hiệu này có thể được đặt tên bằng kỹ thuật tách phương thức:
public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isStrike(frameIndex)) { // ... } return score; } private boolean isStrike(int frameIndex) { return rolls[frameIndex] == 10; }
Khử comment tại mã kiểm thử
Comment tại mã kiểm thử nhằm mô tả magic roll 10. Roll này có thể được đặt tên bằng kỹ thuật tách phương thức:
Trong bài viết trước của mình về lazy-loading images, mình đã giới thiệu chi tiết cả về lý thuyết lẫn thực hành kèm với các kĩ thuật khác nhau. Tuy nhiên nếu bạn đang lúng túng chưa biết cách tích hợp vào dự án sử dụng framework Angular, thì bài viết này sẽ hướng dẫn các bạn tự tay xây dựng một angular module đơn giản hỗ trợ lazy-load images mà không cần sử dụng thư viện bên ngoài. Để tránh làm bài viết quá dài, mình sẽ chỉ trình bày về phần hướng tiếp cận và thiết lập chứ không giải thích lại về “lazy-loading images” là gì nữa nhé.
Trở lại với phong cách hay nói dông dài của mình 😅, mình sẽ phân tích một tí về vấn đề chúng ta sẽ code sắp tới đây. Nếu các bạn muốn thực hành ngay thì có thể bỏ qua phần này.
Trước khi bắt đầu, bạn nên tự hỏi xem project của bạn có phải hỗ trợ các browser cũ hay không:
Nếu KHÔNG nhưng bạn vẫn cần lazyload ảnh nền (background-image): bài viết này sẽ giúp bạn.
Nếu CÓ: không phải nói nhiều, chiến thôi.
<!-- Thật tốt nếu bạn không phải support IE --><img src="sample.png"loading="lazy">
Bạn có thể kiểm tra xem browser nào đã chính thức hỗ trợ thuộc tính loading="lazy" tại Can I Use.
Hướng tiếp cận với directive
Nếu các bạn đã làm việc với Angular một thời gian, thì sẽ dễ dàng đoán được directive là hướng tiếp cận phù hợp với bài toán này. Tuy nhiên việc sử dụng directive cũng có 2 cách như sau:
Nhúng directive trực tiếp vào app.module.ts để có thể sử dụng bất kì chỗ nào.
Tạo một module riêng biệt và nhúng directive vào module đó. Chỗ nào cần sử dụng thì nhúng module đó vào.
Bạn chọn cách nào cũng được, nhưng thông thường mình sẽ chọn cách số 2 theo practice của team mình. Bài viết này mình sẽ thực hiện theo cách số 2 nhé.
Chọn kĩ thuật nào để lazy-load images?
Mình đã thống nhất sử dụng directive rồi, nhưng bên trong directive mình sẽ sử dụng kĩ thuật gì để lazy-load images (trong bài viết trước mình có đề cập đến 3 kĩ thuật đấy)? Câu trả lời là mình sẽ sử dụng cả native và Intersection Observable API nhé. Logic code sẽ như sau:
Nếu browser có hỗ trợ thuộc tính loading="lazy", thì chúng ta tận dụng lợi thế này và để cho browser làm công việc của mình.
Nếu browser không hỗ trợ, hoặc là bạn đang muốn lazy-load ảnh nền (background image), thì chúng ta sẽ fallback về Intersection Observable API.
Thông tin thêm cho bạn, nếu bạn muốn support IE thì cần sử dụng polyfill hoặc có thể chuyển sang dùng kĩ thuật scroll event handler. Các bạn kiểm tra tính tương thích của Intersection Observable tại Can I Use.
Tất cả sẽ được code trong phần tiếp theo.
Bắt tay vào code module images-lazyload
Mình sẽ khởi tạo một project Angular rỗng để thực hành nhé. Các bạn khởi tạo dự án với tên là “angular-demo-lazyload”:
ng new angular-demo-lazyload
Tiếp theo, bạn cần tạo một nơi để chứa module lazy-load. Bạn tạo thư mục tên là “shared” và các file cho directive, service và module như bên dưới.
Giờ thì code thôi, mình có đặt comment chi tiết bên trong code rồi nên sẽ không giải thích nhiều nữa.
Đầu tiên là images-lazyload.directive.ts, chúng ta tận dụng thuộc tính loading để làm directive selector luôn.
import{ Injector, Directive, ElementRef }from'@angular/core';import{ ImagesLazyloadService }from'./images-lazyload.service';
@Directive({// Tận dụng thuộc tính "loading" làm directive selector// Bạn có thể thay đổi thành "img[loading], div[loading]" nếu chỉ muốn target đến thẻ img và div
selector:'[loading]',})exportclassImagesLazyloadDirective{constructor(private injector: Injector,private el: ElementRef,){const img =this.el.nativeElement;// Nếu browser đã support thuộc tính "loading", chúng ta không cần phải làm gì thêm nữa, hãy để nó làm công việc của nó.// Tuy nhiên nếu element không phải là img (nó là background image), thì fallback về intersection observableif('loading'inHTMLImageElement.prototype && img.tagName.toLowerCase()==='img'){
img.src = img.dataset?.src;}else{// fallback sử dụng intersection observable APIconst lazyService =this.injector.get(ImagesLazyloadService);
lazyService.observe(img);}}}
Tiếp theo là images-lazyload.service.ts, phần core của Intersection Observable. Nếu bạn muốn lazy-load với scroll thì chỉ cần thay logic bên trong là được.
import{ Injectable }from'@angular/core';
@Injectable({
providedIn:'root'})exportclassImagesLazyloadService{private observer: IntersectionObserver;constructor(){this.init();}privateinit(){// Khởi tạothis.observer =newIntersectionObserver((entries, imgObserver)=>{
entries.forEach(entry=>{// chưa đến viewport, dừng sớm bớt đau khổif(!entry.isIntersecting){return;}// src được lưu trong data-src, chúng ta copy nó vào src là xong.const lazyImage = entry.target as HTMLImageElement;const src = lazyImage.dataset.src;// nếu ảnh là thẻ img, copy vào src// nếu ảnh là background image, copy vào background-image
lazyImage.tagName.toLowerCase()==='img'? lazyImage.src = src
: lazyImage.style.backgroundImage ='url(\''+ src +'\')';// xong việc thì nên dọn dẹp
lazyImage.removeAttribute('lazy');// tiếp tục dọn dẹp
imgObserver.unobserve(lazyImage);});});}observe(target: Element){// "trải chiếu nằm chờ" tấm ảnh scroll tới viewportthis.observer.observe(target);}}
Cuối cùng là images-lazyload.module.ts, chỉ là khai báo thôi, không có gì đặc biệt.
import{ NgModule }from'@angular/core';import{ ImagesLazyloadDirective }from'./images-lazyload.directive';
@NgModule({
declarations:[ImagesLazyloadDirective],// chúng ta chỉ cần export directive để sử dụng, không cần export service ra ngoài
exports:[ImagesLazyloadDirective],})exportclassImagesLazyloadModule{}
Sử dụng module images-lazyload
Chúng ta đã tạo xong module của lazyload rồi. Nó sẽ như là một thư viện do chính bạn tạo ra vậy, và bạn chỉ cần nhúng vào nơi mà bạn muốn sử dụng. Ở đây mình sẽ nhúng vào app.module.ts.
Bây giờ thì chúng ta có thể sử dụng được rồi. Trong app.component.html, chúng ta hãy thử lazy-load một loạt các tấm ảnh, bao gồm cả thẻ img và ảnh nền sử dụng thẻ div. Các bạn để ý là mình không lazy-load 2 tấm ảnh đầu tiên để tránh lỗi layout-shift. Như có chia sẻ trong bài viết trước, các bạn không nên lazy-load các tấm ảnh above-the-fold nhé.
<img src="https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=753&q=80"width="753"height="500"><img src="https://images.unsplash.com/photo-1519046904884-53103b34b206?w=753&q=80"width="753"height="500"><!-- lưu ý là KHÔNG sử dụng thuộc tính src="..." nhé --><img loading="lazy"data-src="https://images.unsplash.com/photo-1495954484750-af469f2f9be5?w=753&q=80"width="753"height="500"><img loading="lazy"data-src="https://images.unsplash.com/photo-1587502536900-baf0c55a3f74?w=753&q=80"width="753"height="500"><img loading="lazy"data-src="https://images.unsplash.com/photo-1510414842594-a61c69b5ae57?w=753&q=80"width="753"height="500"><img loading="lazy"data-src="https://images.unsplash.com/photo-1471922694854-ff1b63b20054?w=753&q=80"width="753"height="500"><div loading="lazy"data-src="https://images.unsplash.com/photo-1473186578172-c141e6798cf4?w=753&q=80"class="lazy-bg-image"></div><div loading="lazy"data-src="https://images.unsplash.com/photo-1487349384428-12b47aca925e?w=753&q=80"class="lazy-bg-image"></div><div loading="lazy"data-src="https://images.unsplash.com/photo-1527437934671-61474b530017?w=753&q=80"class="lazy-bg-image"></div><div loading="lazy"data-src="https://images.unsplash.com/photo-1473496169904-658ba7c44d8a?w=753&q=80"class="lazy-bg-image"></div>
Với ảnh img, mình hard-code luôn chiều rộng và chiều cao để tránh lỗi layout-shift. Đương nhiên cách này chỉ dùng được nếu bạn đã biết chiều rộng và cao của nó thôi nhé. Thực tế việc này nằm ngoài phạm vi bài viết nên mình dùng tạm cách này để demo cho nhanh, chứ ở production mình không nên dùng mà sẽ có những cách khác “xịn xò” hơn.
Với ảnh background sử dụng thẻ div, nếu bạn không có content bên trong thì bạn sẽ chẳng thấy gì đâu. Bạn thêm một tí CSS vào file app.component.scss
Phần này mình bổ sung thêm nếu bạn nào không thích copy paste và tự maintain code, mà muốn install thư viện bên ngoài để “đảm bảo chất lượng” và hi vọng “họ sẽ maintain giúp mình”, thì mình đã publish module trên thành một thư viện nho nhỏ tại đây: https://github.com/luongvanphuc/ng-lazy-image. Phần hướng dẫn cài đặt và sử dụng các bạn vào xem là thấy.
Hi vọng bài viết của mình giúp ích cho các bạn Angular developer đang tìm cách lazy-load các tấm ảnh của mình. Nếu thấy hữu ích thì hãy upvote để mình có động lực viết tiếp các bài tiếp theo nhé. Hoặc các bạn có thắc mắc hay góp ý thì vui lòng để lại comment bên dưới.
Trước kia khi nói đến design chắc ai cũng nghĩ ngay đến bộ tool của adobe như photoshop, illustrator … Vì nó làm được mọi thứ. Từ xoá phông nền cho đến thiết kế banner, logo website.
1 người mới bắt đầu mà đi dùng bộ adobe này chắc ngộp thở mất. Vì nó trang bị quá nhiều chức năng.
Chính vì trong hoàn cảnh đó mà 1 số công cụ khác đã ra đời giúp dễ dùng hơn. 1 trong những công cụ không thể kể đến đó là Adobe XD.
Bản thân mình cũng rất thích dùng Adobe XD. Vì nó free, mà lại còn nhẹ nữa.
Logo nghệ thuật coding mình cũng dùng adobe XD để thiết kế.
Hôm nay mình sẽ giới thiệu cho các bạn 1 số plugin mình thấy khá là hay khi dùng AdobeXD. Bản thân mình cũng đang dùng nó.
Đây là 1 trong những plugin mình thích nhất. Nó cung cấp cho chúng ta hàng triệu icon free. Từ banner cho đến những ảnh infographics. Toàn hàng ngon cả. Tuy nhiên cũng có 1 số ảnh mất phí.
Plugin này có thể sử dụng được trong cả sketchapp và photoshop nữa.
Đây là 1 trong những plugin sinh ra style guide khá là tiện.
Nếu làm design mà không có style guide cũng giống như việc râu ông nọ cắm cằm bà kia. Màu sắc, font chữ nó sẽ rất lộn xộn, không thống nhất.
Ví dụ như designer tạo ra banner với màu sắc như này. Nhưng mà ông frontend lại dùng với màu sắc khác (không giống hoàn toàn). Rồi có khi lúc dùng font này, lúc dùng font khác.
Ví dụ như khi thiết kế màn hình danh sách người dùng. Khi đó chắc chắn cần phải hiển thị ảnh avatar của người dùng ra. Vậy lúc đó sẽ tìm ảnh ở đâu?
Chắc mọi người sẽ lên mạng search rồi tự chèn bằng tay vào. Cách này cũng được nhưng hơi mất công.
Có 1 cách nhanh hơn là dùng plugin này. Nó sẽ giúp chúng ta chèn ảnh với text dummy 1 cách dễ dàng. Ảnh thì vô cùng phong phú luôn. Không phải lo về nguồn ảnh.
Hiểu về thuộc tính position trong CSS – Khi bạn thiết kế các layout cho website việc chuyển từ file thiết kế theo định dạng HTML (Hypertext Markdown Language) bạn sẽ buộc phải sử dụng thuộc tính position trong CSS. Ví dụ như làm thanh tính năng trên menu, header, v.v. Có thể hiểu nó là thuộc tính xác định loại của phương pháp định vị trí cho thành phần.
Với thuộc tính position chúng ta có 5 giá trị chính cần biết:
Static:Đây được xem là giá trị hiển thị Position trong css một cách mặc định (default), các thành phần sẽ nằm theo thứ tự của văn bản.
Relative: Định vị trí tuyệt đối cho các thành phần, không gây ảnh hưởng tới vị trí ban đầu hay các thành phần khác.
Absolute: Giá trị này sẽ giúp định vị trí tuyệt đối cho thành phần theo thành phần bao ngoài, hoặc ít nhất là theo cửa sổ trình duyệt. Fixed: Định vị trí tương đối cho thành phần theo cửa sổ trình duyệt.
Fixed: Định vị và giúp cho phần tử luôn cố định một chỗ, ví dụ như khi bạn scroll trình duyệt chẳng hạn, phần tử sẽ không thay đổi.
Inherit: Xác định thừa hưởng thuộc tính từ thành phần cha (thành phần bao ngoài).
Trước hết hãy nói về thuộc tính position relative, absolute và các thuộc tính cool ngầu khác
Thuộc tính Position Relative
Thuộc tính position: relative trong CSS giúp Định vị trí tuyệt đối cho các thành phần. Ví dụ:
selector{position: relative;}
Nếu bạn sử dụng thuộc tính này thì sẽ phải sử dụng kèm theo với các thuộc tính căn chỉnh tọa độ của thành phần (lưu ý: các giá trị của các thẻ này là chính là đơn vị đo như px). Top: là cách trên, Bottom: là cách dưới, Left: là cách trái, Right: là cách phải. Hãy cùng nhìn qua đoạn code ví dụ sau đây:
<html><head><metacharset="utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><title>Thuộc tính position trong CSS</title></head><styletype="text/css"media="screen">div{
padding: 40px;
margin: 20px;
width:320px;
border: 2px solid red;
}</style><body><div>TopDev tuyen dung IT hang dau.</div><divclass="relative">TopDev tuyen dung IT hang dau.</div><div>TopDev tuyen dung IT hang dau.</div></body></html>0
Mọi người có thể test thử và thấy rằng các thẻ hiển thị đúng thứ tự, giờ ta có thể thêm đoạn CSS vào class relative như sau:
.relative {position: relative;
/Cách bên trái 260px/
left: 260px;
/Cách bên trên 290px/
top: 290px;
background-color: #e1ab22;
}
Lưu ý, khi bạn bù một vị trí phần tử với position: relative, không gian nó chiếm không di chuyển, vị trí hiện tại của nó sẽ khiến đổi bố cục xung quanh vị trí đó không thay đổi…Tưởng tượng như thế này, position: relative giống như nhân vật có khả năng di chuyển tự do, nhưng luôn luôn liên quan đến nơi ban đầu.
Thuộc tính Position Absolute
Như đã nói ở trên thuộc tính position: absolute trong CSS có tác dụng giúp định vị trí tuyệt đối cho thành phần theo thành phần bao ngoài, hoặc ít nhất là theo cửa sổ trình duyệt. Cụ thể hơn, thuộc tính absolute xác định định tọa độ của thành phần theo một thẻ cha relative (nếu có), Nếu không có thẻ cha thì nó sẽ đi theo body của toàn trang web. Cách sử dụng cũng tương tự như relative.
Dưới đây là ví dụ tương tự như bên trên thay vào đó là thẻ absolute. Các bạn sẽ thấy rõ rằng khi chúng ta di chuyển các thành phần bằng absolute thì các thẻ tiếp theo sẽ được đưa lên vị trí mặc định. Bạn có thể thử ngay nhé.
.absolute {
position: absolute;
/Cách bên trái 260px/
left: 260px;
/Cách bên trên 290px/
top: 290px;
background-color: #e1ab22;
}
Thuộc tính Position Static
Thuộc tínhposition: staticđược xem là giá trị mặc định (default) của position. Đây là các giá trị mà dù bạn có khai báo chúng hay không khai báo thì các phần tử (element) sẽ tự được sắp xếp vị trí một cách như bình thường trên trang web. Bạn có thể nhìn vào ví dụ sau
// Đây là khi bạn không khai báo position
.box-orange {background: Green;
height: 250px;
width: 250px;
}
.box-blue {
background: grey;
height: 250px;
width: 250px;
position: static;
}
//*Sau khi bạn đã khai báo static
Thuộc tính thường được các lập trình viên dùng để định vị một thành phần so với window hiển thị của các trình duyệt. Bạn có thể thấy ví dụ này, khi vào một website nào đó và bạn thử scroll browser, bạn sẽ thấy menu hay button cứ đứng yên một chỗ không thay đổi thì đó chính là position fixed. Giá trị này hoàn toàn không phụ thuộc vào phần tử cha, khi nào scroll trình duyệt là nó hoạt động thôi. Bạn có thể thử tham khảo ví dụ sau đây:
Đây là một thuộc tính khá tương đồng với fixed, bạn có thể xem nó như một sự kết hợp “lưỡng long nhất thể” của relative và fixed. Vì có sự lai tạo này nên nó cũng không được hỗ trợ quá nhiều trong cộng đồng làm web. Nó cũng không sử dụng được trên trình duyệt Internet Explorer cũng như một số phiên bản đầu của Edge nên sẽ dễ gây lỗi. Không khuyến khích các lập trình viên sử dụng
10 khóa học Font-end không thể bỏ qua
TopDev xin giới thiệu đến các bạn đọc top 10 Khóa học, Hướng dẫn, Đào tạo, Lớp học và Chứng chỉ về font-end hoàn toàn miễn phí.
Khóa học này do Đại học Michigan tiến hành phù hợp nhất cho tất cả những ai muốn học cách thiết kế các trang web chuyên nghiệp và tinh tế. Các giảng viên sẽ dạy bạn cách xây dựng một trang web bằng cách sử dụng JavaScript, CSS3 và HTML5.
Đến với khóa học này, bạn còn có thể đảm nhiệm luôn cả vai trò của web developer. Bạn sẽ được dạy về các kỹ thuật công nghệ mới, phát triển các trang web chất lượng có thể hoạt động trên trình duyệt máy tính bàn, máy tính bảng và điện thoại di động.
Ngoài ra, thời gian học của khóa học này khéo dài khoảng 3 tháng, thời gian linh hoạt, lịch học được xếp tùy thuộc vào thời gian của người học.
Khóa học này hứa hẹn sẽ giúp bạn tìm hiểu tất cả các công nghệ, nền tảng cần thiết để phát triển web. Các lớp nhập môn sẽ giới thiệu cho bạn những kiến thức cơ bản về nhiều loại ngôn ngữ khác nhau như HTML, CSS, JS, Node, MongoDB…
Bạn sẽ học được cách tạo các ứng dụng web, game và được tiếp cận nhiều kiến thức phức tạp hơn. Udemy chú trọng cân bằng giữa các lớp lý thuyết và thực hành giúp người mới học dễ dàng theo dõi hơn.
Vào cuối chương trình, bạn sẽ có một loạt kinh nghiệm để đưa vào sơ yếu lý lịch của mình và một loạt các dự án tuyệt vời để giới thiệu. Thời gian học của khóa học này khéo dài khoảng 46 giờ.
Andrei – cha đẻ của khóa học này đã có kinh nghiệm làm việc với tư cách là nhà phát triển cấp cao tại Thung lũng Silicon trước khi quyết định chia sẻ kiến thức phong phú của mình với học viên. Trong khóa học này, anh ấy sẽ dạy bạn viết mã bằng HTML5, CSS, Javascript, React, Node.js, Machine Learning và nhiều hơn nữa.
Nếu bạn đang mong muốn đưa kiến thức Bootstrap của mình để sử dụng và làm việc trong quá trình phát triển ứng dụng front-end thì không cần tìm đâu xa, khóa học này sẽ giúp bạn sử dụng thư viện React và Javascript ES6 để xây dựng ứng dụng.
Bạn sẽ được làm quen với các khía cạnh khác nhau của React, Flux, Redux và học về thuộc tính position trong css. Sau khi đạt được mục tiêu cốt lõi của chương trình, bạn sẽ kết thúc các lớp học với các bài giảng về hỗ trợ và kiểm tra hoạt ảnh React. Vì đây là lớp trình độ trung cấp nên cần có kiến thức về Bootstrap 4, Javascript và các công nghệ web liên quan.
Thời gian học của khóa học này khéo dài 4 tuần, 6 – 8 giờ mỗi tuần.
Với sự tiến bộ của web, sự phát triển của các ứng dụng web cũng đã trải qua một chặng đường dài và đang phát triển mỗi ngày. Vì vậy, khóa học này được đặc biệt thiết kế để giúp bạn xây dựng sự nghiệp trên con đường phát triển ứng dụng web.
Điểm nổi bật của khóa học này là nó phù hợp cho tất cả mọi người ở mọi cấp độ khác nhau. Các bài học xoay quanh về ngôn ngữ và đa dạng các loại công nghệ, do đó học viên sẽ có thể tự do lựa chọn bài giảng phù hợp với bản thân.
Trong cuối các bài giảng, bạn sẽ có dịp tham gia các khóa học nâng cao hơn khi bạn đã nắm rõ hết tất cả kiến thức và có kết quả thực hành tốt. Thời gian học của khóa học này do chính bạn tự điều chỉnh theo năng lực.
Front-End Web Developer Course (LinkedIn Learning – Lynda)
Khóa học này được tạo ra để giúp bạn đạt được các kỹ năng chính, cần thiết để phát triển trải nghiệm người dùng và tương tác trên web. Tìm hiểu mọi kỹ thuật cần thiết để thiết kế và xây dựng mã hướng tới người dùng.
Hơn nữa, các bài giảng dạy bạn làm thế nào để đưa ra các ý tưởng và concept từ cuộc sống vào canvas của trình duyệt bằng cách kết hợp các kỹ năng đồ họa và mã hóa cần thiết. Với hơn 15 mục học tập và nội dung nâng cao.
Thời gian học của khóa học này do chính bạn tự điều chỉnh theo năng lực.
Khóa học này sẽ liệt kê ra các chương trình, khóa học chuyên môn bao gồm các khía cạnh và công nghệ khác nhau cần thiết để phát triển front-end. Có rất nhiều framework và ngôn ngữ được dạy trong khóa học này như React, Bootstrap, Angular JS, bạn cũng sẽ phải hiểu về thuộc tính position trong css…
Các khóa học này có yêu cầu thời lượng dạy khác nhau, bạn có thể chọn khóa nào phù hợp với yêu cầu của mình. Thời gian học của khóa học này do chính bạn tự điều chỉnh theo năng lực.
Kỳ thi chứng chỉ chuyên nghiệp về Font-end này do W3C tạo ra bao gồm tất cả các kỹ thuật cần thiết cần thiết để xây dựng trải nghiệm người dùng phản hồi và tương tác trên web.
Trọng tâm chính là ba ngôn ngữ nền tảng web: CSS, HTML5 và Javascript. Với sự giúp đỡ của các chuyên gia nổi tiếng, bạn được hưỡng dẫn học từng bước cách tạo và triển khai các khái niệm đổi mới và làm việc trên các ví dụ thực tế để hiểu rõ hơn về các chủ đề.
Thời gian học của khóa học này gồm 4 – 6 tuần mỗi khóa, 6 – 10 giờ mỗi tuần, bạn cần học 5 khóa để hoàn thành chứng chỉ này.
Khóa học chuyên nghiệp do Microsoft tạo ra này được thiết kế để giúp bạn xây dựng nền tảng kiến thức vững chắc bằng cách tập trung vào các nguyên tắc cơ bản và giúp bạn giải đáp những thắc mắc của bạn. Các bài giảng sẽ giới thiệu cho bạn về một số công cụ và tính năng được sử dụng thường xuyên nhất với nhiều bản trình diễn khác nhau.
Sẽ có một dự án ở cuối chương trình để giúp bạn tổng hợp, sắp xếp các kiến thức mà bạn đã học. Bạn sẽ phải sử dụng kiến thức của bạn để tự xây dựng một dự án nâng cấp portfolio của bạn.
Sau khi hoàn thành chuỗi 11 khóa học này, bạn sẽ thành thạo và sẵn sàng ứng tuyển vị trí web developer front-end tại công ty bạn chọn hoặc làm nghề tự do.
Thời gian học của khóa học này gồm 11 khóa học, 6 – 10 giờ/tuần/khóa
Lộ trình học tập này của Codecademy được thiết kế dành cho các bạn vừa mới bắt đầu, không có kinh nghiệm trở thành một web developer ở level junor. Bài học bắt đầu với các ngôn ngữ giao diện người dùng như HTML, CSS và JavaScript.
Khi bạn đã nắm vững các công nghệ giao diện người dùng, bạn sẽ được học các kỹ năng khác với trình độ cao hơn. Cuối cùng, bạn sẽ thành thạo trong việc xây dựng và design các trang web.
Thời gian học của khóa học này kéo dài khoảng 30 tuần.
Lời kết
Có thể nói, thuộc tính position trong CSS là một trong những kiến thức cực kỳ quan trọng cần được nắm vững. Các thuộc tính này được sử dụng rất nhiều trong việc làm website hiện nay đặc biệt là khi bạn thực hiện việc cắt layout cũng như làm các thành phần như menu. Bạn nên tìm hiểu thêm một số bài tập về position để sử dụng tính năng này thuần thục hơn nữa.
Sau sự kiện ký kết văn bản ghi nhớ vào ngày 29/07/2020, đánh dấu sự hợp tác giữa Korea IT Cooperation Center tại TP. HCM (KICC HCMC) và Nền tảng tuyển dụng chuyên về IT hàng đầu Việt Nam – TopDev, các lập trình viên càng có nhiều cơ hội hơn khi tìm kiếm nơi phát triển sự nghiệp lập trình phù hợp, đặc biệt là môi trường làm việc chuyên nghiệp cùng nhiều công nghệ tiên tiến tại các công ty Công Nghệ Hàn Quốc.
Đừng bỏ lỡ top 7 cơ hội tiếp theo từ các công ty Công Nghệ Hàn Quốc chất lượng này nhé!
1. VNIB Tech
Mở màn danh sách chính là VNIB TECH, là công ty phần mềm được đầu tư 100% vốn bởi công ty mẹ – Công ty TNHH Innerbus tại Hàn Quốc. Tại đây, bạn sẽ có cơ hội làm việc trong môi trường chuyên nghiệp & linh hoạt, cùng những đồng nghiệp thân thiện, hòa đồng và vui tính.
Bạn đã sẵn sàng cùng VNIB Tech hoàn thành sứ mệnh: “Mang thế giới gần nhau hơn bằng công nghệ”?
⇒ Gia nhập ngay hôm nay tại các vị trí hấp dẫn tại VNIB:
Được thành lập vào năm 2014, PLUS N SOFT chuyên thực hiện nhiều dự án mobile với các công ty hàng đầu trong và ngoài nước. Ngoài ra, công ty đã xây dựng nhiều loại cơ sở hạ tầng khác nhau, giúp tối ưu hóa bộ xử lý để cung cấp các dịch vụ Outsourcing, Business Consulting and Global Platform chất lượng.
Shark Market là công ty hoạt động trong lĩnh vực Thương mại điện tử/bán lẻ. Thông qua website www.sharkmarket.vn và ứng dụng Shark Market, công ty đang nỗ lực không ngừng để hoàn thiện sứ mệnh chọn lọc những sản phẩm tốt nhất, giao hàng hóa thực phẩm tươi ngon nhất đến tay khách hàng.
Bạn đang tìm kiếm cơ hội phát triển tay nghề lập trình tại một trong những công ty thuộc lĩnh vực Thương mại điện tử? Khám phá Shark Market để nắm bắt cơ hội ngay hôm nay.
4. Coconut Silo
Coconut Silo là startup in-house trực thuộc Hyundai Motor Group, ra đời với nhiệm vụ phát triển nền tảng logistics xuyên biên giới ở các nước ASEAN: bắt đầu từ Việt Nam đến Campuchia, Lào và Thái Lan.
Tự hào với với văn hóa làm việc tuyệt vời cùng các công nghệ hiện đại, Coconut Silo hứa hẹn sẽ là nơi để các lập trình viên Việt tỏa sáng tài năng. Đừng quên, tại Coconut Silo còn có cơ hội công tác tại Hàn Quốc, giúp vươn tầm sự nghiệp của các lập trình viên.
Mintpot là một trong những công ty sáng tạo thông minh, chuyên cung cấp các dịch vụ video VR có phụ đề Mint VR. Được thành lập từ năm 2016 cho đến nay, Mintpot luôn theo đuổi mục tiêu tạo ra một cuộc sống tốt hơn với VR.
Môi trường làm việc năng động, trẻ trung, linh hoạt;
Cơ hội phát triển và thăng tiến cao;
Chế độ lương thưởng hấp dẫn cùng nhiều đãi ngộ tốt: Lương tháng 13, tặng Quà Tết, Bánh sinh nhật, Party hàng tháng, Hoạt động giải trí vui vẻ hết mình cùng đội ngũ,…
⇒ Vậy bạn chờ chi không mau lựa chọn 1 trong 2 vị trí đang chiêu mộ tài năng tại Mintpot
6. T&Y
T&Y chuyên hoạt động trong lĩnh vực xuất nhập khẩu máy móc, linh kiện điện tử, gia công phần mềm, đại lý du lịch trong và ngoài nước, hỗ trợ các vấn đề pháp lý cho người Việt tại Hàn…
Đây sẽ là lựa chọn tuyệt vời nếu bạn là C++ Software Engineer, bởi ngoài mức lương cực cao, T&Y còn có nhiều hấp dẫn khác:
Thưởng theo hiệu suất công việc xứng đáng;
Giờ giấc tự do miễn là hoàn thành công việc được giao với hiệu quả tốt nhất.
7. ZOOKIZ
ZOOKIZ là công ty chuyên phát triển các dịch vụ quảng cáo dựa trên các nhân vật hư cấu – fictional characters – như comic, sticker, animation trên các nền tảng social media. ZOOKIZ vẫn đang tìm kiếm những “người bạn” lập trình tài năng tham gia và cùng thực hiện mục tiêu “share love and fun to people”.
Nếu đó là bạn? Đừng chần chừ khám phá thêm về ZOOKIZ nhé!
Cùng với sự xuất hiện tiếp theo của 7 công ty IT Hàn Quốc trên đường đua công nghệ tại Việt Nam, “cái bắt tay chiến lược” của KICC HCMC X TopDev sẽ còn mang đến cho cộng đồng IT Việt Nam nhiều cơ hội mới. Đừng quên chờ đón những bài viết tiếp theo cùng những cơ hội mới hấp dẫn bạn nhé!
________________________________
Dự án được hỗ trợ bởi Korea IT Cooperation Center tại TP. HCM (KICC HCMC) – thuộc Cơ quan Xúc tiến CNTT Hàn Quốc (NIPA), phối hợp cùng TopDev – Nền tảng tuyển dụng CNTT hàng đầu tại Việt Nam với mục đích thúc đẩy tuyển dụng việc làm CNTT cũng như quảng bá cho các công ty IT Hàn Quốc trong cộng đồng lập trình viên lớn nhất tại Việt Nam.
Liên hệ: Korea IT Cooperation Center tại TP. HCM (KICC HCMC)
Bài viết được sự cho phép của tác giả Trần Duy Thanh
Ở bài 1 Tui đã hướng dẫn chi tiết cách tải và cài đặt Android Studio phiên bản năm 2020. ở bài này Tui sẽ trình bày cách sử dụng nó bằng cách tạo một dự án siêu kinh điển “HelloWorld”, tuy nhiên trước khi tạo dự án thì ta cần Go Over qua một số chức năng quan trọng.
Khởi động phần mềm Android Studio phiên bản năm 2020 lên:
Ở màn hình trên ta thấy có tên phương bản và có các mục bên dưới:
Tên chức năng
Ý nghĩa
Start a new Android Studio project
Tạo một dự án mới
Open an existing Android Studio project
Mở một dự án đã có, dự án này được viết bằng công cụ Android Studio
Get from Version Control
Lấy Code từ server về, chắc hạn như: Github, TFS…
Profile or debug APK
Kiểm tra đo lường, debug APK
Import Project (Gradle, eclipse ADT, etc.)
Mở một dự án Android được viết bằng Gradle, Eclipse….
Import an Android code sample
Mở một số code Android mẫu
Ở góc dưới cùng có nút “Configure”, nhấn vào nó:
Tên chức năng
Ý nghĩa
AVD Manager(quan trọng)
Quản lý thiết bị giả lập (điện thoại thông minh, đồng hồ thông minh,…)AVD: Android Virtual Device
SDK Manager(quan trọng)
Quản lý các phiên bản thư viện lập trìnhSDK: Software Development Kit
Settings
Cấu hình đủ loại: giao diện, màu mè
Plugins
Cấu hình Plugins cho Android
Default Project Structer(quan trọng)
Cấu hình Android SDK Location, Android NDK location, JDK location
Check for Updates(quan trọng)
Cập nhật phiên bản mới
Và Các chức năng khác
Bản thân các chức năng này cũng được Android Studio bố trí trong màn hình của 1 Project (các chức năng Tui sẽ lần lượt hướng dẫn chi tiết khi có nhu cầu dùng). Google để ở đây là vì các cấu hình này thường ta chỉ làm 1 lần đầu tiên mà thôi, khi mọi thứ đã ổn rồi thì không cần vào đây phá phách làm gì, hư bột hư đường.
Việc cấu hình mấy chỗ này rất quan trọng, nếu làm sai thì không thể chạy được phần mềm (tuy nhiên nó chỉ xảy ra với các newBie thôi nhé). Nên để không rắc rối thì trong quá trình học, gặp lỗi nào Tui sẽ hướng dẫn cách khắc phục.
Bây giờ ta bắt đầu new 1 dự án Siêu kinh điển nhé “HelloWorld”:
Từ màn hình khởi động phần mềm Android Studio, ta nhấn vào “Start a new Android Studio project“, lúc này Android sẽ yêu cầu chúng ta chọn một dự án mẫu:
Trong này có rất nhiều Template dự án, mới học thì ta chọn loại “Empty Activity”, đừng cố tỏ vẻ nguy hiểm chọn mấy loại khác nha (không cần thiết), chúng ta lưu ý khi làm bất cứ việc gì thì điều quan trọng là phải làm đúng trước đã sau đó mới tới sáng tạo, tới đẹp. Còn ngay từ đầu chưa làm được gì mà đòi đẹp đòi sáng tạo thì thật là hi vọng điên cuồng, đi ngược lại nguyên lý triết học. Khi nắm được căn cơ rồi thì việc bung lụa sau này không còn là vấn đề:
Sau khi chọn “Empty Activity”, ta nhấn “Next” để tiếp tục, lúc này màn hình Cấu hình dự án sẽ xuất hiện ra như dưới đây:
Tên chức năng
Ý nghĩa
Name
Tên Dự án, nên đặt tên có ý nghĩa, nó phải súc tích và toát lên được ý nghĩa của dự án
Package name
Package name rất quan trọng, nó được dùng để tải APK lên Google Play. Được xem như là ứng dụng. Nếu sản phẩm này viết cho ai thì nên đặt theo domain của người đó.Ví dụ:
Khách hàng A có domain tranduythanh.com
Công ty B có domain: duythanhcse.wordpress.com
Công ty B viết dự án cho Khách hàng A, thì package nên đặt là tranduythanh.com (không đặt duythanhcse.wordpress.com) để sau này không xảy ra tranh chấp, cũng như khi đưa lên Google play thì phải lấy theo các tài khoản của A. Vì với bản Mobile nếu ta chỉ có mỗi Coding cũng chả làm gì được, nó còn các file xác thực nữa (đội IT của bên A phải chủ động tư vấn)
Save location
Nơi lưu trữ dự án
Language
Chọn Java (nó có Kotlin) nhưng Tui trình bày Java
Minimum SDK
Chọn tối thiểu là 26
Bây giờ ta đặt các thông số giống như màn hình Tui chụp và sau đó nhấn nút “FINISH“, ráng chờ nha:
ở màn hình trên là Android Studio đang trong quá trình tạo dự án, bạn đừng có manh động, chờ , chờ … tùy vào độ cùi bắp của máy tính chúng ta mà chờ lâu hay mau:
Bạn chờ cho tới khi nó ra được màn hình như trên là đã hoàn tất quá trình tạo một dự án Trong Android Studio rồi đó.
Chúng ta lưu ý, trong Android: Mỗi màn hình nó sẽ có 2 thành phần:
Giao diện (XML) -> mở thư mục res -> layout.
Xử lý code (Java, kotlin, python, C++…)
Như vậy chúng ta đã hoàn thành xong bài học Tạo một dự án trong Android Studio
Mọi developer thì đều chắc cũng đã biết đến sublime text, nói ngắn gọn thì nó là một chương trình dùng để code. Nhưng ở bài viết này tôi sẽ không hướng dẫn về code mà sẽ hướng dẫn về những thủ thuật của sublime text mà sẽ giúp chúng ta tăng hiệu suất làm việc lên.
2. Ví dụ
Tôi sẽ cho ví dụ về một bài tập java Problem1, bài tập này yêu cầu chúng ta tạo class Drink, Food, Cloth, Material và tạo các thuộc tính cho những class đó theo như hình bên dưới.
Nếu ai đã làm qua java hoặc môt ngôn ngữ nào đó thì khi đọc vào bài Prolem1 này thì các bạn sẽ đều hình dung ra cách làm rồi. Đầu tiên là chúng ta sẽ tạo class Drink sau đó sẽ copy các thuộc tính vào và tạo public/private, kiểu dữ liệu cho các thuộc tính đó. Tuy nhiên những class này có số lượng các thuộc tính ít cho nên sẽ không mất thời gian nhiều cho việc này. Giả sử những class sẽ có vài chục hay lên đến cả trăm thuộc tính thì cũng sẽ mất rất nhiều thời gian để tạo.
Vì vậy bài viết này ra đời nhằm giúp cho các bạn rút ngắn được thời gian tạo các thuộc tính cho class. Tôi sẽ sử dụng chức năng trong sublime text để hỗ trợ cho việc này. Hãy cùng bắt đầu nhé.
2.1 Tạo class Drink (Tôi sử dụng eclipse)
2.2 Copy các thuộc tính và kiểu dữ liệu của Drink vào sublime text
2.3 Nhấn giữ nút Shift + Chuột phải, rê chuột từ đầu dòng của vị trí 1 – 6 để chọn toàn bộ tất cả các đầu dòng.
2.4 Gõ vào chữ [private]
2.5 Nhấn giữ nút Ctrl + Shift, và nhấn nút > để chọn tất cả các tên thuộc tính, khi đó ra được hình bên dưới.
2.6 Nhấn phím > (2 lần), để di chuyển con trỏ sang phải 2 ký tự.
2.7 Nhấn giữ nút Shift và nhấn thêm nút End để chọn toàn bộ những kiểu dữ liệu phía sau.
2.8 Nhấn Ctrl + X để cắt toàn bộ kiểu dữ liệu để di chuyển ra vị trí trước của thuộc tính.
2.9 Nhấn phím BackSpace để xóa đi khoảng trắng, sau đó nhấn ; để thêm vào cuối cho các thuộc tính.
2.10 Nhấn giữ Ctrl + Shift và nhấn phím < (Left) để chọn toàn bộ tên các thuộc tính.
2.11 Nhấn phím < để di chuyển sang trái 1 ký tự và Ctrl + V để dán các kiểu dữ liệu mà đã cắt ở 2.8, sau đó nhấn phím space sẽ được như sau.
2.12 Cuối cùng ta copy toàn bộ và paste vào trong eclipse
Quá trình trên tuy nhiều bước nhưng nếu các bạn mà thao tác quen thì sẽ làm rất là nhanh, không mất quá nhiều thời gian. Hãy xem video demo nhé, mình thao tác rất chậm mà chưa tới 1p
Bài viết được sự cho phép của tác giả Trần Hữu Cương
Java Reflection là gì?
Java Refelection là một tính năng (gọi là API hay thư viện cũng được) trong Java. Java Reflection cho phép truy cập các thông tin của đối tượng (tên class, các field, các method) và chỉnh sửa các field của đối tượng (kể cả các field private) trong quá trình run time.
Ta có thể áp dụng Java Reflection trong những trường hợp không biết object được xử lý là gì. (tên class là gì, ở package nào, có những field nào, method nào…).
Ví dụ mình muốn viết một hàm copy 2 đối tượng có thể dùng cho loại đối tượng khác nhau. Thì mình cần phải biết 2 đối tượng có cùng kiểu không, có những field nào, lấy và copy giá trị từng field.
Ngoài ra, với các field, method có modifier là private thì ta không thể truy cập ở bên ngoài class đó. Trong những trường hợp bắt buộc phải gọi, truy cập các field, method private ở bên ngoài class đó thì Reflection là một giải pháp.
Trong trường hợp đã biết rõ cấu trúc class, có quyền truy cập các field, method thì ta không nên sử dụng Java Reflection bởi các lý do sau:
Hiệu năng thấp: Ví dụ nó phải quét classpath để tìm class.
Các vấn đề bảo mật: Việc chỉnh sửa class/object trong quá trình runtime có thể ảnh hưởng tới các thread … khiến cho ứng dụng bị fail.
Khó bảo trì: Việc Reflection khá khó hiểu với người mới và không dễ để debug, nên sẽ rất khó để có thể tìm ra lỗi. Ngoài ra chúng ta cũng không thể check được một số lỗi trong quá trình compile (không tìm thấy class, không tìm thấy field…)
Các thành phần trong Java Reflection
Tương ứng với các thành phần trong một class, thì Java Reflection cũng cung cấp các class tương ứng để ta có thể xử lý:
Class: Đại diện cho class/interface để lấy ra các thông tin của class (tên class, super class, class modifier, các method, các field …)
Constructor: Xử lý các hàm khởi tạo của class
Field: Xử lý các field của class (tên, modifier của field, lấy giá trị, thiết lập giá trị cho object…)
Method: Xử lý các method của class (liệt kê các method, thực thi các method …)
Bạn có thể lấy đối tượng Class thông qua một object với method getClass() hoặc thông qua tên package + tên class với method Class.forName
Để lấy danh cách các hàm khởi tạo, các field, các method ta có thể dùng method getConstructors(), getFields() hoặc getMethods(). Tuy nhiên các method không cho phép lấy các constructor, method, field có modifier là private do đó mình sẽ dùng getDeclaredConstructors(), getDeclaredFields(), getDeclaredMethods().
Method getModifier() trả về modifier của class, method, field nhưng ở dạng số dó đó mình sẽ viết thêm method getModifierName để hiển thị nó dưới dạng String.
Để lấy giá trị hoặc truyền giá trị cho các field của đối tượng bạn có thể dùng method field.set() / field.get()
Demo:
Class name: stackjava.com.reflection.CustomerSuper Class name: stackjava.com.reflection.PersonIs interface: falseConstructors: Number of parameters: 0 - modifier: public Number of parameters: 2 - modifier: publicFields: age - type: int - modifier: private gender - type: class java.lang.String - modifier: protected name - type: class java.lang.String - modifier: public phone - type: class java.lang.String - modifier: defaultMethods: toString - modifier: public getName - modifier: public setName - modifier: public setAge - modifier: public hello - modifier: public setPhone - modifier: public goodbye - modifier: private setGender - modifier: public getPhone - modifier: public getAge - modifier: public getGender - modifier: public
Học lập trình? – Yêu thích và đam mê phát triển website, các ứng dụng, phần mềm, thiết kế game là những lý do khiến nhiều bạn trẻ muốnhọc Code. Tuy nhiên, không phải bạn trẻ nào cũng may mắn có được những định hướng tốt và tìm ra cho mình con đường học tập nhanh nhất.
Nay mình muốn giới thiệu đến anh em 38 blog kỹ thuật của các công ty lớn mà bạn nên theo dõi. Hoặc bạn có thể bookmark chúng để tham khảo khi cần.
Hy vọng danh sách trở thành hành trang cho anh em khởi đầu con đường học Coder, nâng cao kiến thức về các hệ sinh thái công nghệ toàn cầu. Mình biết danh sách trên cũng chưa hẳn là nhiều. Nên nếu có thể, hy vọng anh em sẽ đóng góp thêm một vài blog khác bên dưới comment. Cảm ơn mọi người
Bài viết được sự cho phép của tác giả Vũ Công Tấn Tài
Con trỏ this có lẽ là một khái niệm không mấy xa lạ trong lập trình hướng đối tượng, nó là một thể hiện cho đối tượng đang chứa đoạn mã lệnh đang được thực thi, hiểu nôm na kiểu ngôn ngữ con người là thế này:
Nam học bài rất chăm chỉ vì sẽ có một bài kiểm tra vào cuối tuần, bài kiểm tra này rất quan trọng đối với Nam.
Có thể biểu diễn câu nói này bằng một cách khác như sau:
Nam học bài rất chăm chỉ vì sẽ có một bài kiểm tra vào cuối tuần này, bài kiểm tra này rất quan trọng đối với anh ấy.
Hai câu trên hoàn toàn đồng nghĩa với nhau, mặc dù không nói rõ ràng nhưng tất cả chúng ta đều hiểu “anh ấy” chính là “Nam”. Con trỏ this cũng có ý nghĩa tương tự như thế, và nếu nói theo ngôn ngữ con người, thì con trỏ this chính là một “đại từ nhân xưng” nhằm ám chỉ một đối tượng cụ thể đã được chỉ rõ ở ngữ cảnh trước đó. Con trỏ this được sử dụng rất nhiều trong các đoạn mã JS, và nó cũng là một trong những khái niệm gây ra nhiều sự hiểu lầm (dẫn đến bug) nhất trong ngôn ngữ này.
Để lập trình tốt bằng Javascript thì người lập trình viên buộc phải hiểu rõ cách mà con trỏ this vận hành, sẽ là hơi dài dòng nếu ta muốn tìm hiểu đầy đủ về nó, nhưng một khi đã hiểu về nó, ta sẽ thấy công sức ta bỏ ra không phí một chút nào. Mọi người sẽ cần 1 chút kiên nhẫn để đạt được điều đó
Trong các ngôn ngữ lập trình như C++, C#, Java, PHP hay cả Javascript, con trỏ this thường được sử dụng để chỉ đến object chứa phương thức đang được gọi thực thi, trông ra thì cách dùng này có vẻ tường minh và dễ hiểu, các đoạn mã kiểu đó thường có dạng như:
Khi đoạn code trên được biên dịch và hàm getName() được gọi, thì con trỏ this trong hàm getName() được hiểu là đối tượng Hocsinh1 và this.name chính là chỉ định tới thuộc tính name của đối tượng Hocsinh1 đó. Cũng giống như “đại từ nhân xưng” trong ngôn ngữ nói, this đại diện cho đối tượng (object) ở trong ngữ cảnh (context) được nhắc đến trước đó. Rất dễ hiểu phải không nào, tuy nhiên ta hãy xem xét một chút sâu hơn bên trong, chúng ta cũng sẽ bàn sâu hơn về khái niệm object và context ở những phần tiếp theo.
Cần nói qua một chút về hàm (function) ở trong Javascript, như ta đã biết thì trong JS một hàm cũng chính là một đối tượng (object), và đối tượng thì sẽ có những thuộc tính của riêng nó. Trong JS, khi một hàm được gọi, thì nó sẽ có một thuộc tính là this, và thuộc tính this này chứa giá trị về một đối tượng đang gọi tới hàm này.
Tức là, khi một function được gọi (tạm gọi là function A), thì con trỏ this chứa giá trị của đối tượng gọi tới A, và ta có thể thông qua con trỏ this này để lấy các giá trị thuộc tính khác nằm trong đối tượng vừa gọi tới A.
var Hocsinh1 = {
name: “John”,
getName: function(){
return this.name;
}
};
var _name = Hocsinh1.getName();
Quay lại ví dụ trước, this được khai báo trong hàm getName(), và hàm getName() là hàm sẽ được gọi tới bởi đối tượng Hocsinh1, do đó this ở đây được hiểu là sẽ mang giá trị tham chiếu tới đối tượng Hocsinh1. Tới đây thì cách dùng con trỏ this trong Javascript là tương đồng với các ngôn ngữ khác: giá trị của con trỏ this là rỗng cho tới khi thực sự có một đối tượng gọi tới hàm chứa con trỏ this.
Trong hầu hết mọi trường hợp, this sẽ chứa giá trị của đối tượng gọi tới nó, tuy nhiên việc một hàm trong Javascript cũng chính là 1 đối tượng khiến ta có thể dễ dàng truyền nó vào một tham số của hàm nào đó để sử dụng như một hàm callback, chính điều này sẽ dẫn tới các tình huống mà con trỏ this không thực sự chứa giá trị của đối tượng mà nó thuộc về.
Chúng ta sẽ xem xét 4 trường hợp mà con trỏ this trở nên mơ hồ hơn so với ví dụ ở trên, chúng ta sẽ đi phân tích chi tiết từng trường hợp ở phần tiếp theo:
Con trỏ this trong việc sử dụng hàm callback
Con trỏ this bên trong 1 closure
Con trỏ this trong trường hợp gán hàm cho một biến khác
Mặc dù các ngôn ngữ lập trình hiện đại như C# hoặc Java cũng hỗ trợ hàm callback (như delegate function của C#), tuy nhiên việc sử dụng hàm callback ở trong Javascript thông dụng hơn rất nhiều. Có thể nói nôm na hàm callback là việc chúng ta truyền 1 hàm với vai trò như một tham số vào một hàm khác để có thể kích hoạt hàm đó sau này. Xét ví dụ sau:
//Định nghĩa 1 đối tượng với phương thức hiển thị thuộc tính ra màn hình
var Hocsinh = {
name: “John”,
printName: function(){
console.log(this.name);
}
};
//Bắt sự kiện click chuột lên button, sẽ thực thi hàm hiển thị tên của Hocsinh lên màn hình
$(‘button’).click(Hocsinh.printName);
Theo ý tưởng của người lập trình, khi người dùng click chuột vào button thì hàm printName() sẽ được gọi để hiển thị tên của Hocsinh lên màn hình. Tuy nhiên đoạn code trên sẽ không thể chạy đúng như mong muốn. Lí do bởi vì khi sự kiện click được kích hoạt, thì sự kiện này đang được gán tới đối tượng $(‘button’), chúng ta truyền hàm Hocsinh.printName vào bên trong hàm click() như một đối tượng callback. Lúc này – khi hàm click() được gọi – hàm Hocsinh.printName được kích hoạt, tuy nhiên đối tượng gọi tới hàm này không còn là đối tượng Hocsinh nữa (mà là đối tượng $(‘button’) của jQuery) nên cho trỏ this không còn tham chiếu tới giá trị của đối tượng Hocsinh, dẫn tới việc gọi “this.name” là vô nghĩa.
Sự nhập nhằng này có thể được mô tả ngắn gọn như sau: khi hàm click() kích hoạt hàm callback Hocsinh.printName, thì context của hàm Hocsinh.printName đã bị thay đổi sang đối tượng $(‘button’).
Để đoạn code trên chạy đúng như mong muốn – in ra được name của Hocsinh – thì ta phải đảm bảo được context của hàm callback Hocsinh.printName là chính đối tượng Hocsinh lúc hàm này được gọi. Để thay đổi context, chúng ta có thể dùng hàm Apply(), Call() hay Bind() hỗ trợ sẵn bởi Javascript. Cụ thể trong trường hợp này chúng ta có thể dùng hàm Bind() để gắn context vào hàm callback đó.
//Thay vì viết
$(‘button’).click(Hocsinh.printName);
//Chúng ta sẽ viết
$(‘button’).click(Hocsinh.printName.Bind(Hocsinh));
Đoạn code trên có ý nghĩa là: khi hàm click() gọi tới hàm callback Hocsinh.printName, thì context của hàm callback này là đối tượng Hocsinh chứ không phải đối tượng $(‘button’). Khi đó thì hàm callback Hocsinh.printName sẽ lấy đúng giá trị this.name là Hocsinh.name. Vấn đề được giải quyết!
2. Con trỏ this trong closure
Nói một cách ngắn gọn thì closure là một hàm con (inner function) nằm bên trong 1 hàm khác (outer function). Mọi người có thể tìm hiểu thêm ở đây. Ta đã biết rằng closure thì không thể truy cập tới con trỏ this của hàm cha (outer function), do đó sẽ có thể xuất hiện trường hợp như sau:
var user = {
tournament:"The Masters",
data: [
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
clickHandler: function () {
//Sử dụng con trỏ this ở đây thì OK, this đang mang giá trị tham chiếu tới đối tượng “user”
this.data.forEach (function (person) {
//Tuy nhiên, trong closure này thì this không còn tham chiếu tới đối tượng “user” nữa
// Hàm inner function này không thể truy cập tới this của outer function
console.log (person.name + " is playing at " + this.tournament);
})
}
}
user.clickHandler();
Kết quả của đoạn mã trên như sau:
//Chú ý kết quả undefined
T. Woods is playing at undefined
P. Mickelson is playing at undefined
Như mong đợi của chúng ta, thì this (bôi đỏ) phải tham chiếu tới giá trị của đối tượng user, khi đó ta sẽ lấy được thông tin về tournament của đối tượng user. Tuy nhiên giá trị this bên trong một hàm closure thì không thể truy cập tới giá trị this của hàm bên ngoài (trong trường hợp này nếu không dùng strict mode thì this mang giá trị của biến toàn cục window).
Để sửa lỗi cho trường hợp này, các javascript developer thường giải quyết bằng việc gán giá trị của biến this vào một biến trung gian trước khi gọi closure:
var user = {
tournament:"The Masters",
data: [
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
clickHandler: function () {
//Sử dụng con trỏ this ở đây thì OK, this đang mang giá trị tham chiếu tới đối tượng “user”
var self = this;
this.data.forEach (function (person) {
//Ta sẽ dùng biến self như một biến bình thường trong hàm closure
console.log (person.name + " is playing at " + self.tournament);
});
}
}
user.clickHandler();
Đoạn code trên trông có vẻ kì lạ đối với những người ít code bằng Javascript trước đây, tuy nhiên đây là một tình huống xảy ra khá thường xuyên trong Javascript.
3. Con trỏ this trong trường hợp gán hàm cho một biến khác
Trường hợp ta gán hàm cho một biến khác, cũng sẽ xảy ra tình trạng thay đổi context của hàm nếu được gọi. Ta xét ví dụ sau:
//Định nghĩa 1 đối tượng với phương thức hiển thị thuộc tính ra màn hình
var name = “Peter”;
var Hocsinh = {
name: “John”,
printName: function(){
console.log(this.name);
}
};
//Gán hàm Hocsinh.printName vào một biến
Var printHocsinhName = Hocsinh.printName;
//Gọi hàm printHocsinhName để hiển thị tên học sinh
printHocsinhName();
//------> Kết quả
Peter
Cũng tương tự như các trường hợp đã phân tích ở trên, context của hàm Hocsinh.printName đã bị thay đổi khi ta thực hiện gán hàm cho đối tượng khác. Để giữ nguyên được context là biến Hocsinh thì ta sẽ sửa lại code như sau:
//Gán hàm Hocsinh.printName vào một biến
Var printHocsinhName = Hocsinh.printName.bind(Hocsinh);
//Gọi hàm printHocsinhName để hiển thị tên học sinh
printHocsinhName();
//------> Kết quả
John
4. Con trỏ this trong hàm mượn (borrowing methods)
Hàm mượn (borrowing method) là một trong những khái niệm độc đáo của Javascript. Để hiểu rõ được nó có lẽ cần thêm một bài viết riêng, tuy nhiên mình sẽ đưa ra ví dụ về việc nó thay đổi context của con trỏ this như thế nào. Xét ví dụ sau:
// Chúng ta có 2 đối tượng, 1 đối tượng có hàm computeAvg() và 1 đối tượng thì không
// Chúng ta sẽ thực hiện mượn hàm này
var gameController = {
scores: [10, 15, 20],
avgScore: null,
players: [
{name: "Tommy", playerID: 987, age: 23},
{name: "Pau", playerID: 87, age: 33}
]
};
var appController = {
scores: [30, 40, 50],
avgScore: null,
computeAvg: function () {
var sumOfScores = this.scores.reduce (function (prev, cur, index, array) {
return prev + cur;
});
this.avgScore = sumOfScores / this.scores.length;
}
};
Ta muốn mượn hàm computeAvg() của đối tượng appController để tính điểm trung bình cho đối tượng gameController, vậy cần gọi hàm này như thế nào? Ở đây do hàm computeAvg() thuộc đối tượng appController, nếu muốn thực hiện tính điểm trung bình cho đối tượng gameController thì hàm này phải truy cập được tới các thuộc tính của đối tượng này. Do đó ta cần phải thay đổi context của hàm computeAvg() sang thành đối tượng gameController khi chạy, ta sẽ dùng hàm apply() trong JS để làm được điều này:
Như vậy ta vừa thực hiện dùng hàm mượn (borrowing method) và thay đổi context để thực hiện.
Tóm lại
Qua vài chia sẻ trên đây, hi vọng mọi người có thể hiểu rõ hơn về con trỏ this trong lập trình Javascript. Chúng ta có trong tay các công cụ là các hàm như apply(), bind(), call() để kiểm soát con trỏ this trong nhiều tình huống khác nhau.
Chúng ta thấy rằng, hầu hết mọi rắc rối xảy ra với con trỏ this là do dự thay đổi context của hàm khi được gọi (đã không còn là context ban đầu nơi bản thân hàm được khai báo), cụ thể là trong: hàm callback, closure, gọi từ một đối tượng khác hay khi trong thực thi hàm mượn (borrowing method). Do đó, quy tắc cốt lõi cần nhớ khi làm việc với con trỏ this là: luôn chú tới context của con trỏ this khi hàm được gọi, đảm bảo chúng ta đang sử dụng đúng context của hàm như ý muốn.