Home Blog Page 96

Lộ diện các công ty IT Hàn Quốc sẵn sàng nâng bước sự nghiệp cho lập trình viên Việt

Thị trường IT Việt Nam đang trên nhịp tăng trưởng mạnh và ngày càng trở nên sôi động hơn với làn sóng đầu tư từ nước ngoài, mang đến nhiều cơ hội phát triển cho các lập trình viên Việt. Tiêu biểu trong số đó, không thể không kể đến Hàn Quốc – Một trong những cường quốc về CNTT đang hướng sự chú ý đến nguồn lực IT trẻ và tài năng tại Việt Nam.

Tiếp nối thành công của dự án hợp tác 2020, KICC HCMC cùng TopDev tiếp tục mang đến chương trình hợp tác năm 2021 với thông điệp “Make Your IT Career Outstanding – Khởi sắc sự nghiệp IT của bạn”. Theo đó là những hoạt động phối hợp với mục đích kết nối các việc làm ngành CNTT tại các doanh nghiệp IT Hàn Quốc với đối tượng Lập Trình Viên Việt Nam. Từ đó hỗ trợ, hợp tác và thúc đẩy tuyển dụng việc làm công nghệ thông tin cho các công ty Hàn Quốc và tạo thêm nhiều cơ hội để các tài năng IT Việt Nam sở hữu những tấm vé gia nhập vào các doanh nghiệp công nghệ hàng đầu của Hàn Quốc hiện đang có mặt tại Việt Nam. 

Cùng khám phá xem Top 7 công ty công nghệ đến từ Hàn Quốc xuất hiện tiếp theo trong kỳ này sẽ mang đến những điều thú vị và cơ hội nào cho các tài năng IT Việt Nam nhé!

1. Shinhan DS Vietnam Company Limited

Mở màn cho danh sách kỳ này là sự xuất hiện của Shinhan DS Vietnam – thành viên của SHINHAN, một trong những tập đoàn tài chính hàng đầu với hơn 100 năm uy tín tại Hàn Quốc. Góp mặt vào thị trường IT Việt Nam từ tháng 5/2018, Shinhan DS Vietnam hứa hẹn là bước nhảy vọt ấn tượng của tập đoàn, mang đến những dịch vụ CNTT chất lượng cao, có được sự tin tưởng và ủng hộ từ khách hàng.

⇒ Nếu bạn là Experienced Software Developer (Junior/ Senior) đang tìm kiếm cơ hội trải nghiệm môi trường làm việc tuyệt vời tại một trong những tập đoàn danh tiếng, Shinhan DS Vietnam hứa hẹn là điểm đến lý tưởng cho hành trình phát triển sự nghiệp của bạn.   

2. LOTTE Data Communication Company Vietnam

LOTTE Data Communication Company Vietnam tự hào là nhà cung cấp các giải pháp và Dịch vụ IT chất lượng cho các công ty con thuộc Tập đoàn LOTTE tại Việt Nam trong hơn thập kỷ qua. Với đội ngũ chuyên gia, kỹ sư dày dặn kinh nghiệm, công ty luôn chiếm được niềm tin từ phía Đối tác và Khách hàng.

Kế thừa tất cả tinh hoa từ Công ty mẹ, LOTTE Data Communication Việt Nam kết nối và phát triển mạng lưới khách hàng thuộc mọi lĩnh vực từ Bán lẻ, Sản xuất đến Tài chính, Dịch vụ công… bằng những giải pháp bắt kịp xu hướng Công nghệ của thế giới như Triển khai hệ thống ra vào cho cao ốc, An Ninh nhận diện khuôn mặt, Smart Parking, Thu phí tự động,…

Tiếp tục góp mặt vào dự án KICCxTopDev 2021, LOTTE Data Communication Việt Nam đặc biệt mang đến cơ hội chuyển mình bứt phá dành cho các nhân tài IT tại Việt Nam với vị trí Senior System Administrator. Khám phá ngay để không bỏ lỡ những trải nghiệm nghề nghiệp thú vị bạn nhé!

3. Lecle Vietnam JSC

Lecle là công ty phần mềm toàn cầu có trụ sở chính tại Hàn Quốc cùng nhiều văn phòng đặt tại Mỹ, Singapore và Việt Nam. Với phương châm “We work and enjoy hard”, Lecle Vietnam nỗ lực đem đến môi trường làm việc đáng mơ ước, hứa hẹn là “bệ phóng” năng lực cho sự nghiệp bạn đồng thời tạo “sân chơi” lý tưởng giúp gắn kết mỗi thành viên trong công ty.

Lecle Vietnam JSC đang trên hành trình tìm kiếm tài năng IT đất Việt cho vị trí Front-end Developer (JavaScript, ReactJS) với mức lương hấp dẫn cùng loạt đặc quyền phong phú:

  • Được trang bị Macbook xịn sò
  • Chế độ nghỉ phép và thưởng xứng đáng
  • “Tấm vé” tham dự sự kiện và hoạt động thú vị
  • Cơ hội onsite Hàn Quốc

>>> Và nếu môi trường làm việc tuyệt vời tại Lecle Vietnam JSC đã đủ để kích hoạt tài năng trong bạn? Vậy đừng chần chờ thêm nữa, nắm bắt cơ hội tốt ngay hôm nay!

4. NHN VIỆT NAM

NHN Việt Nam là công ty con của NHN Corporation, phụ trách phát triển công nghệ cho các dịch vụ của NHN tại Đông Nam Á, tự hào với Comico – một trong những ứng dụng webtoon hàng đầu tại Việt Nam. Đồng thời, công ty cũng là đầu mối cung cấp nền tảng có giá trị giúp mở rộng dịch vụ trò chơi di động rộng khắp các nước Đông Nam Á.

Không dừng lại ở đó, sự xuất hiện của NHN Việt Nam trong kỳ này còn mang đến “tấm vé” khởi sắc sự nghiệp cho các lập trình viên tài năng với nhiều cơ hội bùng nổ năng lực đang chờ bạn tại 1 trong 2 vị trí:

– Manual Tester

– Senior Frontend (Javascript, HTML, CSS)

5. CAFE24 VINA

CAFE24 VINA là nền tảng thương mại điện tử toàn cầu, nơi cung cấp các dịch vụ giải pháp E-commerce tổng hợp như xây dựng cửa hàng trực tuyến, thanh toán, vận chuyển, marketing, liên kết với các sàn TMĐT.

Với kinh nghiệm 20 năm hoạt động tại Hàn Quốc với nhiều chi nhánh tại Nhật bản, Đài Loan, Mỹ,… CAFE24 VINA hướng tới việc mở rộng thị trường rộng khắp khu vực Đông Nam Á, trong đó có Việt Nam. Và để thực hiện mục tiêu đó, công ty đang ráo riết tìm kiếm Front-End Developer cùng với loạt cơ hội phát triển sự nghiệp và đặc quyền xứng đáng sẵn sàng trao tay.

6. DataStreams Asia

DataStreams Asia là doanh nghiệp Hàn Quốc hiện đang dẫn đầu thị trường về tích hợp quản lý chất lượng dữ liệu. Với công nghệ và đội ngũ chuyên môn có trình độ tốt, DataStreams Asia tự hào đã đưa ra các giải pháp với hiệu suất cao giúp xử lý và quản lý dữ liệu an toàn, hiệu quả.

Tính đến nay, Datastreams Asia đã thành lập nhiều chi nhánh ở Mỹ, Trung Quốc, Nhật Bản, Việt Nam…và đang dần mở rộng thị trường ra nước ngoài thông qua hợp tác với các đối tác toàn cầu như doanh nghiệp phát triển ứng dụng, công ty tư vấn công nghệ thông tin, đại lý…

Nếu bạn yêu thích lĩnh vực Dữ liệu hoặc đang tìm kiếm cơ hội tiếp xúc các công nghệ mới như ioT, big data,… thì DataStreams Asia chính là điểm đến phù hợp dành cho bạn. Bắt ngay “slot” gia nhập tại vị trí IT Manager và sẵn sàng chinh phục đỉnh cao sự nghiệp từ hôm nay!

7. Beyondnet VN

Beyondnet VN là nhà cung cấp dịch vụ thoại và internet cấp 2 (ISP) hỗ trợ các công ty Hàn Quốc hoạt động tại Việt Nam, Philippines và Hàn Quốc. Hiện tại Beyondnet đang tập trung vào việc cung cấp kết nối internet nhanh chóng cho khách hàng Hàn Quốc ở nước ngoài thông qua mạng đường trục toàn cầu và hỗ trợ dịch vụ viễn thông địa phương và bảo trì CNTT.

Và nếu bạn đã sẵn sàng để trở thành nhân tố quan trọng góp phần làm nên thành công của Beyondnet VN? Nhanh tay bắt ngay cơ hội tại vị trí System Engineer để không bỏ lỡ những đặc quyền hấp dẫn đang chờ bạn tại Beyondnet VN.

Với sự xuất hiện của Top 7 công ty công nghệ Hàn Quốc trong kỳ này, TopDev hi vọng bạn có thêm những thông tin hữu ích và lựa chọn được “bến đỗ” phù hợp để thỏa sức bùng nổ năng lực, phát huy thế mạnh của bản thân. Và đừng quên đón đọc những bài viết tiếp theo và chớp ngay những cơ hội mới hấp dẫn cho sự nghiệp bạn nhé!

Thông tin chi tiết về dự án vui lòng truy cập tại đây

Về KICC HCMC và NIPA

Được thành lập vào ngày 23 tháng 5 năm 2019, KICC HCMC (KICC Hồ Chí Minh) là văn phòng thứ 6 trên toàn cầu và thứ 2 tại Việt Nam. KICC là văn phòng quốc tế trực thuộc Bộ Khoa học – Công nghệ Thông tin Hàn Quốc (MSIT) và Cơ quan Xúc tiến Công nghệ Thông tin – Truyền thông (NIPA) với mục đích giúp đỡ việc kinh doanh quốc tế của những công ty về Công nghệ Thông tin (CNTT) của Hàn Quốc. KICC có 06 văn phòng ở Thung lũng Silicon (Mỹ), Tokyo (Nhật), Bắc Kinh (Trung Quốc), Singapore, Hà Nội (Việt Nam) và Hồ Chí Minh (Việt Nam).

NIPA là tổ chức phi lợi nhuận từ Chính phủ Hàn Quốc và là thành viên của Bộ Khoa học – Công nghệ Thông tin Hàn Quốc, chịu trách nhiệm trong việc hỗ trợ các công ty và các chuyên gia CNTT. NIPA hiện dẫn đầu trong kiến thức về cơ sở hạ tầng kinh tế xã hội và phát triển kinh tế quốc gia bằng việc xúc tiến khả năng cạnh tranh của toàn ngành công nghiệp thông qua sự tiến bộ kỹ thuật CNTT và công nghiệp.

Thông tin liên hệ:

  • Hotline: 84 28 35208135 (Vietnamese) | 84 28 35208136 (Korean)
  • E-mail: HCMC@nipa.kr
  • Địa chỉ: 135 Hai Bà Trưng, Phường Bến Nghé, Quận 1, Thành phố Hồ Chí Minh

Về TopDev – nền tảng tuyển dụng IT

Với hơn 300.000 profile lập trình viên đồng thời sở hữu Cộng đồng Lập trình viên lớn nhất Việt Nam, TopDev hiện là một trong những nền tảng tuyển dụng chuyên về IT hàng đầu tại Việt Nam.  Ngoài ra, TopDev là một trong những đơn vị tiên phong ở lĩnh vực IT tại Việt Nam, giúp xây dựng và phát triển thương hiệu tuyển dụng – Employer Brand cho hàng trăm công ty công nghệ trong và ngoài nước. Đây còn là đơn vị chuyên khảo sát, phân tích và phát hành các báo cáo quý, năm về thị trường và nhân lực IT tại Việt Nam. (Báo cáo thị trường IT tại đây)

Tìm việc IT lương cao, đãi ngộ tốt trên TopDev ngay!

CDN là gì? – CDN hoạt động như thế nào?

CDN là gì? – CDN hoạt động như thế nào?

Bài viết được sự cho phép của tác giả Kiên Nguyễn

CDN, viết tắt của từ Content Delivery Network (Mạng lưới phân phối nội dung) hiện nay đã trở nên vô cùng quen thuộc với chúng ta.

CDN có thể bắt gặp ở mọi nơi. Dù có chấp nhận hay không thì bản thân chúng ta vẫn tương tác với CDN hàng ngày. Từ lướt web, xem youtube hay tìm kiếm bất cứ thông tin gì. Chẳng hạn như bài viết này cũng có thể đang được lấy từ bộ đêmc của Content Delivery Network nào đó.

  CDN - Chỉ 1 giây làm đổi thay tâm trí khách hàng
  Cách làm HTTPS hoạt động trên local trong 5 phút

Vậy chính xác CDN – Content Delivery Network là gì?

1. Tại sao lại cần CDN?

Trước tiên, để hiểu tại sao chúng ta cần Content Delivery Network, ta cần hiểu từ khóa LATENCY (độ trễ).

LATENCY the annoying delay that occur. from the moment you request to load a web page to the moment its content actually appears onscreen.

Độ trễ được biết tới như là khoảng thời gian từ lúc chúng ta yêu cầu tải trang web cho tới khi thật sự nhìn thấy nội dung trên trang web đó.

Thông thường, nếu máy chủ chưa nội dung trang web ở Việt Nam và người request yêu cầu nội dung ở Việt Nam thì rất ít khi nhận ra độ trễ.

Độ trễ thường bị ảnh hưởng bởi một vài yếu tố sau:

  • Nội dung trang web
  • Khoảng cách vật lí
  • Tốc độ mạng

Tuy nhiên, yếu tố ảnh hưởng nhiều nhất vẫn là khoảng cách vật lí.

2. CDN ra đời

Để giải quyết vấn đề về độ trễ và giúp thời gian tải trang nhanh hơn, mạng lưới nội dung (Content Delivery Network) ra đời.

Có thể tìm hiểu thêm về định nghĩa qua video này

Là mạng lưới truyền tải thông tin được cache từ trước. CDN giúp tăng tốc độ tải trang, giảm bớt độ trễ do khoảng cách vật lí gây ra.

3. CDN hoạt động như thế nào?

Trong mạng lưới Content Delivery. Mỗi điểm hiện diện (location) được gọi là một PoPs.

Để tăng thời gian phản hồi giữa client và server (người dùng và trang web), các PoPs (node trong mạng lưới) sẽ lưu nội dung trang web vào bộ nhớ (cached) của mình và làm mới nó thường xuyên.

Nhờ vào mạng lưới dày đặc Content Delivery Network, người dùng sẽ chỉ kết nối với một node gần mình nhất là sẽ có thông tin. Qua đó tăng tốc độ tải trang
Nguồn ảnh / Source: hashthemes.com

Khi người dùng yêu cầu nội dung trang web, người dùng sẽ không trực tiếp truy cập tới trang web (ở bờ Tây nước Mỹ chẳng hạn) mà chỉ truy cập với một điểm CDN gần mình nhất.

4. Khi nào nên sử dụng CDN?

Tất nhiên, ai cũng muốn nội dung của mình tải nhanh, load nhanh. Nhưng chú ý rằng không phải trường hợp nào cũng cần sử dụng CDN.

Nếu content của bạn chỉ có một lượng nhỏ truy cập ở vị trí địa lí gần nơi đặt máy chủ, không cần thiết phải dùng CDN.

Ngược lại, nếu nội dung của bạn được truy cập và sử dụng ở khắp nơi trên thế giới. Đăng kí tham gia mạng lưới Content delivery network là cần thiết giúp tăng trải nghiệm người dùng. Một số dịch vụ tốt hiện nay có thể kể tới là:

cdn-la-gi-cdn-optimoleQuảng cáo về pricing của Optimole cho thấy rằng càng nhiều CDN location thì tốc độ tải nội dung càng cao
Nguồn / Source: optimole.com
cdn là gì, content delivery network là gìCDN thế hệ mới của CloudFlare tăng hai lần tốc độ tải, với mạng lưới rộng lớn ở khắp nơi trên thế giới. Cloudflare quả là lựa chọn không tồi.
Nguồn / Source: CloudFlare

5. Tham khảo

Hiểu biết về CDN tất nhiên không thể bỏ qua một khái niệm phổ biến khác là VPN. Có thể tìm hiểu về VPN qua bài viết này nha.

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Building Microservices Application – Phần 1: Sử dụng Netflix Eureka, Ribbon và Zuul

building

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Đây là bài viết thứ nhất (index start từ 0 😀 ) trong series Building Microservices Application với Spring Boot. Trong bài viết mở đầu series đã giới thiệu một cách tổng quan các “viên gạch” cần có khi xây dựng ứng dụng Microservices. Trong bài viết này, hãy bắt tay vào những viên gạch đầu tiên CẦN thiết nhất bao gồm: API Gateway, Load balancer và Service Discovery.

  Building Microservices Application - Phần mở đầu: Bức tranh tổng thể
  Các thao tác cơ bản với Database SQL Server (tạo mới database, table,...)

SPRING BOOT, SPRING CLOUD VÀ NETFLIX OSS

Spring Boot là một dự án nổi bật trong hệ sinh thái Spring Framework. Nếu như trước đây, công đoạn khởi tạo một dự án Spring khá vất vả từ việc khai báo các dependency trong file pom.xml cho đến cấu hình bằng XML hoặc annotation phức tạp, thì giờ đây với Spring Boot, chúng ta có thể tạo các ứng dụng Spring một cách nhanh chóng và cấu hình cũng đơn giản hơn.

Như các bạn biết, để cấu hình, setup một project web đơn giản cũng tốn kha khá thời gian, vậy để setup, quản lý cấu hình, dependency cho một Microservices application sẽ còn phức tạp hơn nhiều. Tuy nhiên với Spring Boot, bạn sẽ thấy nó giúp ích khá nhiều cho chúng ta. Có thể coi Spring Boot như một project configuration manager của bạn, hãy cho Spring Boot biết bạn muốn tạo ứng dụng gồm những tính năng gì, ví dụ như: Web service, Web MVC, Microservices với API Gateway, Load balancer và Service Discovery, Circuit breaker,… Spring Boot sẽ tự biết làm gì để tạo ra project skeleton với đầy đủ những thứ bạn cần, và thậm chí, bạn có thể bấm Run luôn cái project mới tạo ra luôn đấy.

Spring Cloud là nền tảng khá mới mẻ trong gia đình Spring.io dùng để xây dựng microservice một cách nhanh chóng. Spring Cloud cung cấp các công cụ cho các developer để nhanh chóng xây dựng một số common patterns trong các hệ thống phân tán (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, cluster state). Chúng sẽ hoạt động tốt trong bất kỳ môi trường phân tán nào, bao gồm máy tính xách tay của chính developer, các data center hoặc trên cloud.

Bản thân hệ sinh thái Spring không tự build hết tất cả các viên gạch cần để xây dựng ứng dụng Microservices. Thay vào đó, có một kho gạch dành cho Microservices được Netflix ban đầu phát triển trong nội bộ của họ để xây dựng dịch vụ xem phim trực tuyến nổi tiếng của họ và sau đó public ra dưới dạng open source với cái tên Netflix OSS (Open Source Software). Và Spring đơn giản chỉ làm nhiệm vụ wrap chúng lại và dùng trong hệ sinh thái của Spring (tất nhiên Spring nó còn wrap nhiều thằng khác nữa). Bằng cách kết hợp Spring Boot, Spring Cloud và Netflix OSS sẽ đủ cung cấp các công cụ và nguyên liệu cần thiết nhất để giúp bạn có thể nhanh chóng và dễ dàng xây dựng các Microservices của mình.

1. BẢNG NGUYÊN LIỆU

Nhìn vào bảng dưới đây sẽ cho thấy cách mapping giữa các viên gạch chúng ta đã nói trong phần mở đầu và các công nghệ để giải quyết

1

Trong bài viết này, hãy cùng làm việc với 3 chú: Eureka, Ribbon và Zuul

Netflix Eureka – Là một Service Discovery Server cho phép các dịch vụ microservices tự đăng ký mình vào danh sách các services hoạt động lúc khởi chạy.

Netflix Ribbon – với chức năng Dynamic Routing và Load Balancing có thể được sử dụng bởi Service client để tra cứu dịch vụ lúc runtime. Ribbon sử dụng thông tin có sẵn trong Eureka để định vị các instance thích hợp. Nếu tìm thấy nhiều hơn một instance, Ribbon sẽ áp dụng cân bằng tải để phân phối các reuqest đến các instance rảnh việc nhất. Ribbon không chạy dưới dạng một dịch vụ riêng biệt mà thay vào đó no là một thành phần được nhúng trong mỗi Service client.

Netflix Zuul – Đóng vai trò như một Edge Server hoặc gatekeeper với thế giới bên ngoài, không cho phép bất kỳ yêu cầu bên ngoài trái phép nào đi qua. Các request đi tới services đều phải qua anh chàng Zuul này để check hàng trước. Zuul sử dụng Ribbon để tra cứu các dịch vụ sẵn có và định tuyến yêu cầu bên ngoài đến instance dịch vụ thích hợp. Trong bài đăng trên blog này, tôi sẽ chỉ sử dụng Zuul như một điểm vào (entry point), các khía cạnh về bảo mật sẽ có trong các bài đăng trên blog sắp tới. Các bạn có thể tìm hiểu thêm về GateKeeper hay nói cách khác là API Gateway ở đây nhé

2. KIẾN TRÚC

2

Có 4 business services ( màu xanh lá cây ):

Ba core services chịu trách nhiệm xử lý thông tin liên quan đến sản phẩm, đề xuất và đánh giá.
Một composite service có thể tổng hợp thông tin từ ba core services và tạo ra chế độ xem thông tin sản phẩm cùng với các đánh giá và đề xuất của một sản phẩm.

Để hỗ trợ các business services, chúng ta sử dụng các infrastructure servives sau đây ( màu xanh dương ):

  • Service Discovery Server (Netflix Eureka)
  • Dynamic Routing and Load Balancer (Netflix Ribbon)
  • Edge Server (Netflix Zuul)

3. SOURCE CODE

Bạn có thể checkout source code dưới này về. Lưu ý, cần cài đặt Java SE 8 và Git.

$ git clone https://github.com/callistaenterprise/blog-microservices.git
$ cd blog-microservices
$ git checkout -b B1 M1.1

Structure của source code

2.1

Mỗi thành phần được xây dựng một cách riêng biệt (hãy nhớ rằng chúng ta không phải xây dựng các ứng dụng nguyên khối 🙂 vì vậy mỗi thành phần có build file riêng của chúng. Sử dụng Gradle làm build system, nếu bạn chưa cài đặt Gradle, build file sẽ download xuống cho bạn. Run shell script dưới đây để build.

$ ./build-all.sh

Hoặc nếu đang sử dụng Windows thì có thể run:

build-all.bat!

4. DIỄN GIẢI SOURCE CODE

Chúng ta hãy xem nhanh một số cấu trúc mã nguồn chính. Mỗi microservice được phát triển dưới dạng ứng dụng Spring Boot độc lập và sử dụng Undertow, một container Servlet 3.1 nhẹ làm máy chủ web của nó. Spring MVC được sử dụng để thực hiện các dịch vụ dựa trên REST. Spring RestTemplate được sử dụng để thực hiện các cuộc gọi đi. Nếu muốn biết thêm về các công nghệ cốt lõi này, bạn có thể xem bài đăng trên blog sau đây .

Bây giờ hãy tập trung vào cách sử dụng các chức năng trong Spring Cloud và Netflix OSS!

4.1 GRADLE DEPENDENCIES

Theo tinh thần của Spring Boot, Spring Cloud đã định nghĩa một tập hợp các dependencies mặc định. Để sử dụng Eureka và Ribbon trong microservice, cần thêm config dưới đây vào build file:

compile("org.springframework.cloud:spring-cloud-starter-eureka:1.0.0.RELEASE")

Để xem ví dụ hoàn chỉnh, hãy xem product-service/build.gradle.

Để có thể thiết lập máy chủ Eureka, hãy thêm phụ thuộc sau:

compile('org.springframework.cloud:spring-cloud-starter-eureka-server:1.0.0.RELEASE')

Để xem ví dụ hoàn chỉnh, hãy xem discovery-server/build.gradle.

Tip: các bạn có thể vào trang https://start.spring.io/ và lựa chọn thực đơn (các tính năng) cho ứng dụng microservices của mình, Spring Boot sẽ giúp bạn tìm cách dependencies cần thiết

4.2. INFRASTRUCTURE SERVERS

Thiết lập một máy chủ cơ sở hạ tầng (Infrastructure Server) dựa trên Spring Cloud và OSS Netflix thực sự dễ dàng. Ví dụ: đối với máy chủ Eureka, hãy thêm @EnableEurekaServer annotation vào ứng dụng Spring Boot chuẩn:

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}

Để xem ví dụ hoàn chỉnh, hãy xem EurekaApplication.java .

Để dựng một máy chủ Zuul, bạn có thể thêm @EnableZuulProxy. Để xem ví dụ hoàn chỉnh, hãy xem ZuulApplication.java.

Với các annotations đơn giản này, bạn đã có thể tạo ra các server đỉnh, làm được việc rồi đấy. Theo mặc định, Zuul thiết lập một route cho mọi dịch vụ mà nó có thể tìm thấy ở Eureka. Với cấu hình sau trong application.yml – chúng ta hãy giới hạn các routes để chỉ cho phép các cuộc gọi đến composite product service:

zuul:
ignoredServices: "*"
routes:
productcomposite:
path: /productcomposite/**

Để xem ví dụ hoàn chỉnh, hãy xem edge-server/application.yml.

4.3 BUSINESS SERVICE

Để tự động đăng ký microservices với Eureka, thêm một @EnableDiscoveryClient annotation vào ứng dụng Spring Boot.

@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {

public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}

Để xem ví dụ hoàn chỉnh, hãy xem ProductServiceApplication.java.

Để tìm và gọi một instance của một microservice, sử dụng Ribbon và một Spring RestTemplate như sau:

@Autowired
private LoadBalancerClient loadBalancer;
...
public ResponseEntity getReviews(int productId) {

ServiceInstance instance = loadBalancer.choose("review");
URI uri = instance.getUri();
...
response = restTemplate.getForEntity(url, String.class);

Service client chỉ cần biết tên của dịch vụ (ví dụ như review), Ribbon (tức là LoadBalancerClient ) sẽ tìm thấy một instance dịch vụ và trả về URI của nó cho Service client.

Để có một ví dụ hoàn chỉnh, hãy xem Util.java và ProductCompositeIntegration.java .

5. KHỞI CHẠY CÁC MICROSERVICES

Trong bài đăng trên blog này, chúng ta sẽ start/run các microservices như các process java độc lập trên môi trường ở máy local. Về sau, chúng ta sẽ tìm hiểu cách triển khai các microservices trên cloud và Docker containers!

Để có thể chạy một số lệnh được sử dụng bên dưới, cần phải cài đặt các cURL và jq .

Mỗi microservice được start bằng cách sử dụng lệnh ./gradlew bootRun.

Đầu tiên hãy start các infrastructure services (Eureka và Zuul)

$ cd .../blog-microservices/microservices

$ cd support/discovery-server; ./gradlew bootRun
$ cd support/edge-server; ./gradlew bootRun

Sau đó start các business services

$ cd core/product-service; ./gradlew bootRun
$ cd core/recommendation-service; ./gradlew bootRun
$ cd core/review-service; ./gradlew bootRun
$ cd composite/product-composite-service; ./gradlew bootRun

Nếu đang sử dụng Windows, bạn có thể thực thi tập tin bat tương ứng start-all.bat!

Khi các microservices được khởi động và được đăng ký với máy chủ khám phá dịch vụ, chúng sẽ ghi các thông tin sau vào log:

DiscoveryClient … – registration status: 204

Trong ứng dụng web khám phá dịch vụ, bây giờ chúng ta có thể thấy bốn business services và edge server ( http: // localhost: 8761 ):

3

5.1 TEST

Bắt đầu gọi composite service thông qua edge server ở port 8765 (xem application.yml) và như chúng ta đã thấy ở trên, chúng ta có thể sử dụng đường dẫn /productcomposite/** để tiếp cận product-composite service thông qua edge server. Kết quả trả về:

$ curl -s localhost:8765/productcomposite/product/1 | jq .

{
"name": "name",
"productId": 1,
"recommendations": [
{
"author": "Author 1",
"rate": 1,
"recommendationId": 1
},
...
],
"reviews": [
{
"author": "Author 1",
"reviewId": 1,
"subject": "Subject 1"
},
...
],
"weight": 123
}

5.2 DYNAMIC LOAD BALANCING

Để tránh lỗi hoặc sự cố mạng tạm thời, sẽ có nhiều instance dịch vụ cùng loại chạy một lúc và sử dụng bộ cân bằng tải để phân bổ các request đến các instance. Vì chúng ta đang sử dụng các port được cấp phát động và một máy chủ khám phá dịch vụ nên rất dễ dàng để thêm một instance mới. Ví dụ, chỉ cần bắt start một review service mới và nó sẽ cấp phát một port mới một cách tự động và chính nó sẽ đăng ký với máy chủ khám phá dịch vụ.

$ cd .../blog-microservices/microservices/core/review-service
$ ./gradlew bootRun

Sau một lúc, bạn có thể check lại trong Eureka server ( http: // localhost: 8761 ):

4

Nếu chạy lệnh curl trước đó ( curl -s localhost:8765/productcomposite/product/1 | jq .) một vài lần và nhìn vào log của hai service instance, bạn sẽ thấy cách bộ cân bằng tải tự động phân bổ các request tới hai instance mà không cần bất kỳ cấu hình thủ công nào:

5.png

6. TÓM TẮT

Chúng ta đã biết được sự lợi hại của bộ ba Spring Boot, Spring Cloud và Netflix OSS để đơn giản hóa việc phát triển và triển khai các microservices một cách tự động và mượt mà. Khi các service instance mới được start, chúng sẽ tự động được phát hiện bởi bộ cân bằng tải thông qua máy chủ khám phá dịch vụ và có thể bắt đầu nhận “công việc”. Sử dụng Edge server để kiểm soát các microservices nào được giao tiếp với bên ngoài.

7. TIẾP THEO LÀ GÌ

Có một số câu hỏi vẫn chưa được trả lời, ví dụ như:

  • Làm gì khi có lỗi xảy ra hoặc một hoặc thậm chí nhiều service bị down
  • Làm thế nào để ngăn chặn truy cập trái phép vào API thông qua Edger server?
  • Làm cách nào để có được bức tranh tổng hợp tốt về tình hình đang diễn ra trong toàn hệ thống microservice, ví dụ: tại sao đơn đặt hàng số 123456 chưa được giao?

Trong các bài viết sắp tới trong loạt bài về Building Microservices Application, chúng ta sẽ xem xét cách tăng khả năng phục hồi và chịu lỗi (resilience) bằng bộ ngắt mạch (circuit breaker), sử dụng OAuth 2 để hạn chế quyền truy cập bên ngoài. Chúng ta cũng sẽ xem xét cách sử dụng ELK stack để thu thập log từ tất cả các microservices theo cách tập trung và hợp nhất và more and more.

Series này là phần tiếp theo series Microservices: Từ Thiết Kế Đến Triển Khai, tập trung vào việc hiện thực hóa các khái niệm đã mô tả ở phần lý thuyết. Hi vọng sẽ giúp ích được cho các bạn khi làm quen với microservies. Các bạn có thể tham khảo thêm về phần Architecture căn bản ở đây nhé.

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Jobs for Developer hấp dẫn trên TopDev

Tăng tốc độ tối đa cho ứng dụng viết bằng Angular JS

Tăng tốc độ tối đa cho ứng dụng viết bằng Angular JS

Bài viết được sự cho phép của tác giả Tino Phạm

Gắn bó với AngularJS cũng khoảng 2 năm rồi. Thật sự nhìn lại nhưng app mình làm với nó vẫn chưa gọi là “good” về chất lượng (performance). Có thể do: code sh*t, hoặc do cách tổ chức (structure) chưa tốt, hoặc cũng có thể do dữ liệu quá lớn,… Đến lúc phải nhìn lại xem nó đang bị ảnh hưởng do yếu tố nào? Làm sao để cải thiện và làm thế nào để cải thiện.

Ở phạm vi bài viết này, mình không bàn về vấn đề code sh*t hay không và cũng không bàn về cách tổ chức code sao cho tốt. Vì đó là việc tùy vào đẳng cấp của mỗi người, tùy vào dự án, tùy vào tâm lý xã hội tình cảm,… Và việc thực hiện nó cần cả team và cần có một TechLead giỏi để giúp thực hiện tốt. Ở đây mình chỉ tập trung nói việc hiểu và sử dụng một công nghệ như thế nào cho tốt thôi. Và chủ đề của bài này là tập trung vào AngularJS.

  8 lợi thế khi sử dụng Polymer so với Angular và React

  Buils một ứng dụng thời tiết sử dụng AngularJS

Theo như ng-conf team định nghĩa thế nào là “chậm” trong ứng dụng dùng AngularJS? thì họ có nêu ra một số vấn đề như sau:

  • $apply > 25ms
  • Click handler > 100ms
  • Show a new page > 1s
  • If > 10s => User will give up
  • 200ms or less is ideal

Mình sẽ chia sẽ một số cách để có thể tăng thêm tốc độ cho ứng dụng web dùng AngularJS và Javascript mà mình đã tìm hiểu và thử nghiệm.

  1. Các file js, css nên được nén lại (minified): việc minify js (javascript) các file css (stylesheet) sẽ giúp bạn có được các file js và css nhẹ hơn, tải lên nhanh hơn và bảo mật hơn.
  2. Tắt chế độ debug của AngularJs
    Trước khi release package bạn nên tắt chế độ này để có thể tăng hiệu suất ứng dụng.Tại sao vậy? Vì, mặc định AngularJS tự động thêm các siêu dữ liệu vào trong DOM để hỗ trợ các công cụ phát triển và debug.Vậy siêu dữ liệu đó là những gì? Khi bạn debug ứng dụng bạn sẽ thấy các class như ‘ng-bind’, ‘ng-scope’, ‘ng-isolate-scope’ được gắn vào DOM.Làm sào tắt chế độ này bây giờ? Đây là cách dùng:

    
    app.config(['$compileProvider', function($compileProvider){
    $compileProvider.debugInfoEnabled(false);
    }]);
    

    Ngoài ra, khi đã tắt chế độ debug rồi bạn vẫn có thể load lại chế độ này tạm thời để debug bằng cách gọi hàm angular.reloadWithDebugInfo() bên trong console tool

  3. Sử dụng phương thức useApplyAsync() cho các đối tượng $http
    Nếu như ứng dụng của bạn có rất nhiều $http request cùng lúc để lấy dữ liệu về. Thì mỗi $http response nó sẽ gọi digest() để cập nhật lại DOM.
    Trong các ứng dụng lớn, khi khởi động ứng dụng bạn cần lấy rất nhiều dữ liệu về cùng một lúc rồi mới hiện lên giao diện. thì nên sử dụng useApplyAsync() để đồng bộ lại tất cả các response này và gọi digest() một lần thôi. Trong các ứng dụng nhỏ (có ít request cùng lúc) bạn sẽ không thấy được sự khác biệt khi dùng phương thức này.
    Vậy làm sao dùng nó trong ứng dụng đây? Xem ví dụ sau:

    
    app.config(function($httpProvider){
    $httpProvider.useApplyAsync(1000); //true
    });
    
  4. Sử dụng $templateCache
    Nếu ứng dụng của bạn có nhiều templates vậy thì server cần phải tải tất cả các templates này về trước khi hiện lên cho người dùng thấy. Sử dụng $templateCache sẽ giúp hạn chế việc tải lại các templates này. Nghĩa là template chỉ được tải 1 lần sau đó AngularJs lưu vào cache và nhưng request sau đó sẽ được gọi từ cache để load template.
    Oh, sử dụng thế nào? Có nhiều cách để chúng ta dùng template. Cách để dễ bảo trì và trực quan nhất là viết template vào 1 file html riêng rồi dùng $TemplateCache service put nó vào. Xem ví dụ sau:

    
    app.run(function($templateCache){
    $templateCache.put('templateId.html', 'This is my content');
    //Or get a template cache
    $templateCache.get('path/templateId.html');
    });
    
  5. Tránh dùng quá nhiều $watch
    Phần này khá quan trọng, nó ảnh hưởng đến performance rất nhiều. Đầu tiên chúng ta cần hiểu được $watch được tạo ra khi nào? watcher được tạo ra khi:
    – Dùng binding {{ item }}
    – Dùng biến scope: scope: { bar: ‘=’}
    – Dùng Filter {{ value | myFilter }}
    – Dùng các directive: ng-show, ng-hide, ng-repeat, ng-change, ng-model, ng-click,….
    – Dùng $http event
    – Dùng $q để resolve promise
    – Dùng $timeout, $interval
    – Dùng method $scope.$watch()Vì sao vậy? vì tất cả những thứ này sẽ gọi xuống $digest() để cập nhật lại DOM. Chính vì thể khi bạn cũng cần hạn chế việc dùng $apply() vì nó cũng sẽ gọi $digest(), hoặc khi gọi trực tiếp $digest().Bạn cần hiểu cách làm việc của AngularJs như thế này: $watch() sẽ làm thêm cái đó rồi gọi $apply(). Trong $apply có thể làm thêm việc gì đó rồi gọi $digest(). $digest sẽ kiểm tra xem đối tượng được watch có thay đổi gì không, nếu có sẽ cập nhật DOM
    Tóm lại, có nhiều watchers sẽ tạo ra nhiều digest cycle


    Ảnh từ angular.org

    Vậy làm bây giờ? ứng dụng của tôi cần  phải dùng tất cả những thứ ở trên, không lẽ không dùng.
    Ở đây chúng ta hiểu được khi nào tạo ra watcher rồi, chúng ta chỉ hạn chế tạo ra quá nhiều watcher không cần thiết. Cho nên,  tùy trường hợp, bạn cần phải xem xét để có thể áp dụng đúng.Vậy giờ làm sao để hạn chế việc tạo ra watcher?
    OK, tôi sẽ hướng dẫn cho bạn làm thế nào. Nhưng bạn cần xem xét trường hợp nào nên dùng và không nên dùng để tránh ảnh hương đến logic của ứng dụng.a) Chỉ sử dụng two-way binding (binding 2 chiều) khi nào dữ liệu của bạn cần thay đổi model. Trong AngularJs để dùng two-way binding bạn dùng ng-model. Bạn có thể sử dụng {{ item }} hoặc ng-binding nếu dữ liệu không cần thay đổi model của bạn.- Sử dụng ngModelOptions để hạn chế gọi digest() liên tục mà cần chờ một khoảng thời gian nào đó rồi mới gọi digest (trường hợp user input). Cách dùng:

    
    <span ng-model="user.username" ng-model-options="{ update: 'blur'}"></span>
    <span ng-model="search.keyword" ng-model-options="{ debounce: 500}"></span>
    <span ng-model="search.keyword" ng-model-options="{ debounce: {default: 500, blur: 0}}"></span>
    

    b) Sử dùng bind-one (binding 1 lần) nếu giá trị không cần thay đổi. Từ AngularJs 1.3 trơ đi đã hỗ trợ cho chúng ta cú pháp bind-one như sau:

    {{ :: item }}

    , chỉ cần thêm dấu :: trước tên biến. Khi dùng bind-one sẽ không tạo ra watcher.

    c) Dùng ng-if, ng-switch thay cho ng-show/ng-hide. Vì sao vậy? vì ng-if, ng-switch rẽ remove element html nếu false nên các watcher cũng sẽ bị remove theo. Còn ng-show/ng-hide element html luôn luôn tồn tại và nò dùng CSS để ẩn/ hiện trên giao diện nên watcher cho những element này vẫn tồn tại. Đây là ví dụ dùng ng-switch:

    d) Nên giảm thiểu sử dụng ng-repeat. Giảm thiểu là sao? nghĩa là nếu bạn có 1000 items cần show lên GUI bạn nên dùng paging hoặc lazy-load để show từng phần dữ liệu. Có một vấn đề là watcher được tao ra rất nhiếu khi dùng ng-repeat


    Bạn cũng có thể kết hợp bind-one với ng-repeat hạn chế việc tao ra watcher. Như sau:

    AngualrJs hỗ trợ thêm cú pháp track by khi dùng với ng-repeat như sau:

    Với việc dùng track by ng-repeat sẽ không cần $destroy và tạo lại DOM một cách không cần thiết.

  6. Sử dụng $destroy
    Nên $destroy: $timeout, $interval, $watch, $on, các events của element DOM: click, change,…

    
    var timeout = $timeout(function(){
    //do something
    }, 500);
    
    var interval = $interval(function(){
    //do something
    }, 500);
    
    var watchfunc = $scope.$watch("item", function(newVal, oldVal){
    if(newVal !== oldVal){
    //do something
    watchfunc(); //remove watch after done
    }
    });
    
    $scope.$on('$destroy', function () {
    $timeout.cancel(timeout);
    $interval.cancel(interval);
    watchfunc(); // apply the same for $scope.on
    });
    
    scope.$on('$destroy', function () {
    angular.element(window).off('click', windowClick);
    });

Hy vọng với những gì mình đã trình bày sẽ giúp các bạn có inscrease performance cho ứng dụng của mình tốt hơn khi dùng với AngularJs. Có thế bạn sẽ không thể áp dụng tất cả các cách mình đã nói. Vậy tùy trường hợp mà bạn nên xem xét dùng thế nào cho hợp lý nhé.

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Mức Lương Của Các Vị Trí Lập Trình Viên Trong Năm 2021 & Xu Hướng Thời Gian Tới

mức lương lập trình viên

Theo số liệu trong Báo Cáo Thị Trường IT Việt Nam 2021 – Developers Recruitment State do TopDev thực hiện, thị trường nhân lực ngành công nghệ thông tin năm 2021 sẽ tăng đến 36,5% so với năm 2020 (khoảng 117.180 lập trình viên). Nhu cầu tuyển dụng tăng lên mở ra cơ hội cho các lập trình viên tìm kiếm những công việc tốt cùng mức thu nhập hấp dẫn. Tùy theo năng lực, kỹ năng và sự tự tin của bản thân mà mức lương dành cho các vị trí lập trình viên sẽ khác nhau.

Mức lương lập trình viên dựa vào công nghệ

Hiện nay, danh sách top đầu những công nghệ được trả lương cao nhất trên thị trường chia là hai nhóm lớn, chủ yếu do ảnh hưởng từ quá trình chuyển đổi kỹ thuật số trên toàn thế giới:

  • High tech liên quan đến các xu hướng như AI/ML (Kubernetes, TensorFlows, Python)
  • Điện toán đám mây (AWS, GCP, Azure)

mức lương lập trình viên

Theo đó, mức lương lập trình viên cao nhất (với các đối tượng có khoảng 3 năm kinh nghiệm) dựa theo công nghệ hiện đang thuộc về AWS với 1.752$/tháng, TensorFlows nằm trong khoảng 1.703$/tháng

Mức lương khi làm việc với các công nghệ cơ bản về phát triển web, hệ thống và thiết bị di động hiện vẫn đang giữ ở mức khá cao, như công nghệ lập trình bằng ngôn ngữ Python khoảng 1.290$/tháng, C++ ở mức 1.196$/tháng.

Tính lương gross sang net chuẩn, trải nghiệm ngay!

Mức lương lập trình viên dựa vào trình độ

Theo thống kê Vietnam IT Market Report 2021 của TopDev, trong khoảng 5 năm làm việc đầu tiên sau khi ra trường, mức lương của lập trình viên sẽ dao động trong mức 342$/tháng (fresher) đến dưới 1.161$/tháng với vị trí Senior

Sau 5 năm làm việc, mức lương lập trình viên lúc này sẽ được chi trả dựa vào vị trí làm việc cũng như trách nhiệm đối với hoạt động kinh doanh. Mức lương tối thiểu của vị trí giám đốc hoặc các chuyên viên cấp cao thường là 2.200$/tháng. Tùy theo định hướng kinh doanh của công ty, các vị trí với trình độ chuyên môn khác nhau sẽ được trả mức lương phù hợp.

mức lương lập trình viên theo trình độ

Mức lương lập trình viên dựa vào chuyên ngành

3 ngành có mức thu nhập cao nhất thị trường IT hiện nay là Security, High Tech và Fintech. Trong đó, lĩnh vực Hightech – công nghệ cao như AI, IoT, điện toán đám mây,… được coi là xu hướng bắt buộc trong năm 2021 và thời gian tới. Nhờ đó, những lập trình viên có năng lực trong chuyên ngành này đang sở hữu lợi thế cạnh tranh mạnh hơn hẳn so với các lĩnh vực khác trong ngành IT. 

Bên cạnh đó, hầu như trong tất cả các hệ thống quản trị doanh nghiệp, đặc biệt với các ngân hàng, Fintech là yếu tố cực kỳ quan trọng và cần thiết để điều hành và quản lý công việc. Đó là lý do mức lương của lập trình viên theo chuyên ngành này đứng đầu trong top các ngành có lương cao.

Mức lương lập trình viên dựa vào vị trí

mức lương lập trình viên dựa vào vị trí

Bên cạnh những khó khăn do dịch Covid-19 gây ra, không thể phủ nhận đây cũng là chất xúc tác cho việc đổi mới và chuyển sang kỹ thuật số trong kinh doanh. Dịch vụ đám mây và DevOps chiếm vai trò quan trọng hơn rất nhiều trong việc duy trì và phát triển doanh nghiệp. Đó là lí do nhu cầu tuyển dụng các vị trí liên quan đến kỹ sư Cloud/DevOps đang tăng mạnh và mức lương cho các vị trí này cũng theo đó tăng rất cao trong khoảng 2.057$/tháng.

Các vị trí quản lý cấp cao hơn như CTO, CIO và Quản lý công nghệ đòi hỏi trách nhiệm cũng như năng lực cao hơn hẳn so với các vị trí khác, là mục tiêu nghề nghiệp của những ai theo đuổi ngành IT. Ở vai trò quản lý sẽ đòi hỏi khả năng chuyên môn tốt hơn, khả năng quản lý nhân sự trong team, quản lý hiệu suất công việc, quản trị rủi ro, quản trị an ninh mạng cũng như đảm bảo được sự ổn định tốt nhất cho team. Mức lương cho các vị trí Tech Management hiện trong khoảng 5.776$/tháng, Technical Director và Engineering Manager dao động ở mức 4.165$/tháng.

Trên đây là thống kê về mức lương của một số vị trí, ngành nghề, chuyên môn trong lĩnh vực công nghệ thông tin. Để tìm hiểu thông tin chi tiết hơn về các số liệu khác cũng như các vấn đề tuyển dụng và nhân lực của ngành IT, mời bạn tải Báo Cáo Thị Trường IT Việt Nam 2021 – Developers Recruitment State do TopDev phát hành.

Tải ngay báo cáo

Tìm việc IT lương cao, đãi ngộ tốt trên TopDev ngay!

Báo Cáo Thị Trường IT Việt Nam Năm 2021: Chuyển Mình Vào Cuộc Cạnh Tranh Tri Thức Toàn Cầu

thị trường IT
báo cáo thị trường IT năm 2021

Kể từ khi đại dịch bùng phát, ngành công nghệ thông tin cũng như mọi ngành nghề khác phải đối diện với không ít khó khăn và liên tục thay đổi để thích nghi với một hoàn cảnh mới. Trong bối cảnh các nước trên thế giới đang dần hồi phục và “đứng lên” từ chính những khó khăn, thị trường IT Việt Nam cũng đang phát triển trong bối cảnh “bình thường mới” với những câu chuyện mới về kinh doanh và công nghệ. Theo như thông tin trong Báo Cáo Thị Trường IT Việt Nam 2021 – Developers Recruitment State do TopDev thực hiện, giờ đây chính là cuộc cạnh tranh của tri thức, của sự cấp tiến trong tư duy về thị trường công nghệ. Thành công sẽ đến với những ai biết nắm bắt đúng thời cơ và tận dụng trí lực để phát triển.

DOWNLOAD

Tổng quan tình hình ngành Công nghệ thông tin

Dù chịu ảnh hưởng của nhiều làn sóng dịch Covid-19 liên tiếp, tuy nhiên kinh tế Việt Nam nói chung và ngành Công nghệ thông tin vẫn đạt được những thành tựu đáng kể. Theo công bố của Tổng cục Thống kê, Việt Nam hiện đứng thứ 2 trên thế giới về sản xuất điện thoại di động và linh kiện, đứng thứ 10 thế giới về sản xuất linh kiện điện tử. Đây cũng là hai yếu tố chính giúp lĩnh vực công nghệ thông tin và truyền thông của Việt Nam trở thành ngành xuất siêu lớn nhất trong sự tăng trưởng chung của toàn nền kinh tế.

Nhờ tình hình khả quan này mà trong Dự thảo Chiến lược quốc gia về vấn đề công ty công nghệ số Việt Nam đã nêu rõ mục tiêu, cho đến năm 2030 Việt Nam sẽ tiếp tục tập trung vào việc phát triển các công ty với 4 loại hình công nghệ số:

  1. Các công ty phát triển công nghệ cốt lõi
  2. Các công ty phát triển các sản phẩm và dịch vụ công nghệ kỹ thuật số
  3. Các công ty phát triển các giải pháp công nghệ kỹ thuật số
  4. Khởi nghiệp công nghệ số

Việt Nam đề ra mục tiêu đến năm 2030 đạt ít nhất 100.000 doanh nghiệp công nghệ số và có 1,5 triệu nhân viên trong lĩnh vực kỹ thuật số. Đây chính là cơ hội để các doanh nghiệp hoạt động trong lĩnh vực công nghệ có thể bứt phá và mở rộng hơn quy mô kinh doanh nhờ các chính sách hỗ trợ từ nhà nước. Cũng nhờ đó, dư địa việc làm trong lĩnh vực này sẽ còn dồi dào hơn.

Chính phủ Việt Nam đang tiếp tục xây dựng các chính sách để thu hút đầu tư nước ngoài vào lĩnh vực IT cũng như định hình cơ cấu chuyển đổi số quốc gia rõ ràng, hiệu quả. Việt Nam chú trọng đầu tư mạnh vào chi phí cạnh tranh, cơ sở hạ tầng với các tổ hợp công nghệ thông tin, các khu công nghệ cao để trở thành điểm đến hấp dẫn với nhà đầu tư công nghệ nước ngoài.

Nhu cầu nhân lực của thị trường IT Việt Nam 2021

nhân lực ngành IT

Theo các số liệu thống kê từ năm 2018 – 2022 được đưa ra, nhu cầu nhân lực cho ngành công nghệ thông tin tại Việt Nam vẫn đang tăng cao liên tục. Dựa trên Báo cáo về thị trường IT Việt Nam 2021 của TopDev, đến năm 2021 Việt Nam sẽ còn cần đến 450.000 nhân lực trong ngành công nghệ thông tin. Trong khi đó, số lượng lập trình viên hiện tại của Việt Nam mới chỉ đạt khoảng 430.000 người.

Thực tế là, số lượng ngành học về công nghệ thông tin ở các trường đại học đang mở rộng ngày càng nhiều cũng như số lượng cử nhân tốt nghiệp chuyên ngành này vẫn tăng cao qua mỗi năm, tại sao vẫn có sự chênh lệch này? Sự thiếu hụt này chủ yếu là do trình độ của lập trình viên và yêu cầu doanh nghiệp đặt ra vẫn chưa thực sự cân bằng với nhau. Trong số hơn 55.000 sinh viên công nghệ thông tin tốt nghiệp mỗi năm chỉ có khoảng 16.500 sinh viên (30%) đáp ứng được những kỹ năng và chuyên môn mà doanh nghiệp cần.

Cuộc cạnh tranh khó khăn hơn với nhiều yêu cầu về chuyên môn và kỹ năng

Nhu cầu tuyển dụng trong lĩnh vực IT vẫn luôn trên đà tăng trưởng nhanh và mạnh. Do sự thay đổi và ảnh hưởng của tình hình kinh tế – xã hội chung cũng như dựa trên các kỹ năng cứng và kỹ năng mềm mà lập trình viên sở hữu, mức lương cũng như trình độ sẽ được phân loại một cách rõ ràng hơn trong thời gian tới.

thị trường IT

Bên cạnh kỹ năng chuyên môn vững vàng, những kỹ năng mềm như khả năng tư duy phát triển, giao tiếp, quản lý thời gian, trình độ ngoại ngữ,… cũng là yếu tố quan trọng trong quá trình tuyển chọn và đánh giá ứng viên của nhà tuyển dụng. 

Chính sự biến động của tình hình chung do dịch bệnh gây ra cũng như sự đổi mới liên tục của công nghệ đòi hỏi ở các lập trình viên khả năng thích ứng nhanh và nhạy bén với mọi sự biến đổi. Các lập trình viên cần nâng cao kỹ năng công nghệ của bản thân với sự hiểu biết về các công nghệ mới và đột phá như Cybersecurity, DevOps, AI và Machine Learning, Cloud Computing,…

Nhìn chung, khó khăn là vấn đề chung mà mọi người phải cùng vượt qua, nhất là trong thời điểm dịch bệnh vẫn đang lan rộng hiện nay. Với tinh thần tỉnh táo và bản lĩnh trí tuệ, Việt Nam vẫn cho thấy được những tín hiệu khả quan trong sự tăng trưởng về kinh tế cũng như thu hút các nhà đầu tư chiến lược từ nước ngoài, trong đó có cả lĩnh vực công nghệ thông tin. Để tìm hiểu chi tiết hơn về thị trường IT Việt Nam trong nửa đầu năm 2021 và xu hướng trong thời gian tới, bạn có thể đón đọc Vietnam IT Market Report 2021 – Developers Recruitment State do TopDev thực hiện tại đây.

 

Tuốt tuồn tuột về Java 8 – những thay đổi lớn!

Tuốt tuồn tuột về Java 8 – những thay đổi lớn!

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Java 8 xuất hiện với nhiều cải tiến rõ rệt, hãy cùng Kieblog tìm hiểu xem nhưng thay đổi lớn nào đã giúp Java 8 trở nên mạnh mẽ và linh động hơn.

Bài viết dưới đây liệt kê ra 5 THAY ĐỔI LỚN có ở JAVA 8. Hãy cùng đọc nhé!

  10 câu hỏi javascript để nâng cao trình độ
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java

1. Phương thức forEach()

Cập nhật này đúng ra thì là quá chậm trễ so với .NET. Visual Basic hay C# đều đã có forEach từ lâu. Hãy quên đi những câu for xưa cũ để chuyển qua sử dụng ForEach

Phương thức này cũng được hỗ trợ tốt bởi Iterator (java.lang.Interable). Cùng xem xét ví dụ add tất cả các đối tượng i vào list như sau:

// Cách cũ truyền thống từ xưa vẫn sử dụng
// Nhìn thôi đã thấy rườm rà, chán
List<Integer> listDanhSach = new ArrayList<Integer>();
for(int i=0; i<69; i++) listDanhSach.add(i);

// Loop với Iterator
Iterator<Integer> it = listDanhSach.iterator();
while(it.hasNext()){
Integer i = it.next();
}

Bùm, với Java 8, chỉ đơn giản là:

// Easy for ence với forEach
listDanhsachA.forEach(a -> listDanhSachB.add(a.getB()));

2. Java 8 Lambda

Nhắc tới Java 8 mà không nhắc tới Lambda qủa thật là một sự thiếu sót to lớn. Lambda giúp cho functional programming (lập trình hàm) trở nên đơn giản hơn nhiều.

Syntax: parameter -> expression body. Dấu mũi tên biểu thị cho reference (tham chiếu tới cái gì đó)

Java Lambda liệt kê thành 4 loại sau đây:

Optional type declaration − No need to declare the type of a parameter. The compiler can inference the same from the value of the parameter

Không cần khai báo tham số. Trình compiler có thể tự suy luận các tham số cần thiết

Optional parenthesis around parameter − No need to declare a single parameter in parenthesis. For multiple parameters, parentheses are required.

Trường hợp có sử dụng tham số (nhiều hơn 2), bắt buộc phải khai báo bên trong cặp ngoặc ().

Optional curly braces − No need to use curly braces in expression body if the body contains a single statement.

Loại này không cần dấu ngoặc nhọn, nếu phần xử lí chỉ đơn giản được gói gọn trong phần body

Optional return keyword − The compiler automatically returns the value if the body has a single expression to return the value.

Loại sử dụng từ khóa return. Trình compiler sẽ tự động return về giá trị nếu body có một biểu thức trả về các giá trị.

Ông nào muốn tìm hiểu sâu hơn về Lambda có thể tham khảo bài viết về Java 8 Lambda ở Kieblog

3. Stream API

Sự xuất hiện của Stream trong Java 8 như là sự cứu rỗi cho các đoạn source loằng ngoằng trong Java. Nay với Stream, tất cả chỉ gói gọn trong một dòng code.

Đối với Stream thì Kieblog đã có một bài viết tương đối chi tiết và đặc sắc (Tuốt tuồn tuột về Stream trong Java 8).

4. Method reference

So với các ngôn ngữ như Scala hay Ruby on Rail đã có từ lâu. Method Reference cũng chỉ mới xuất hiện trên Java 8, khá trễ nhưng có còn hơn không.

Từ sau khi được release trên bản Java 8, Method Reference giúp code dễ đọc hơn, đỡ rườm rà, một số trường hợp còn dễ hiểu hơn cả Lambda.

Sơ bộ có thể chia Method Reference thành 4 loại chính:

4.1 Reference tới phương thức static

Các refer này khá sử dụng, với syntax là ContainingClass::methodName.

Cùng xem xét ví dụ sau đây:

// Cách viết này sử dụng lambda kiểm tra i có tồn tại trong list không
boolean isVisible = list.stream().anyMatch(i -> Item.isVisible(i));

Còn đây là cách sử dụng Java 8 method reference

// Chỉ đơn giản sử dụng ::, không cần care param, khá gọn
boolean isVisible = list.stream().anyMatch(Item::isVisible);

4.2 Reference tới instance của method

Khi new lên một instance method. Syntax có hơi khác hơn chút xíu: containingInstance::methodName

// Các dùng tương tự
Item item = new Item()
boolean isVisible = list.stream().anyMatch(item::isVisible())

4.3 Reference tới Instance Method của Object các kiểu đặc biệt

Loại này có syntax: ContainingType::methodName. Trường hợp nếu sử dụng với String, Long, Integer, … đều sử dụng được tất cả các instance method

// Tính tổng các String item trong list không empty
int count = list.stream().filter(String::isEmpty).count();

4.4 Reference tới Constructor

Loại này có ít bạn nhớ (sử dụng với từ khóa ::new), nhưng thực tế vẫn có thể reference tới constructor theo kiểu như sau:

// Tính tổng các String item trong list không empty
Stream<Item> stream = list.stream().map(Item::new);

5. Optional <T>

Trước khi Java 8 xuất hiện, để handle các trường hợp xuất hiện Exception thường rất vất vả. Catch đủ thứ, lỗi nào có thể văng ra thì catch lỗi đó. Đôi khi là hoa cả mắt xem lỗi đó catch ở đâu.

Class Optional <T> xuất hiện, giúp handle các khả năng văng NPE (Null Pointer Exception).

Handle NPE với Optional rõ ràng dễ hơn hẳn, cho phép ta cấu hình một số việc cần làm khi gặp NPE, trường hợp không có, chỉ đơn giản là thực thi một đoạn code nào đó.

// Lấy ra một list, nếu list khác null thì trả về list
// Nếu list null thì cần new ArrayList<>
List<String> listA = doAnyThingToGetList();
List<String> listB = list != null ? list : new ArrayList<>();

Sau khi áp dụng Optional:

// Đối với Java 8 Optional - chỉ đơn giản là một dòng code
List<String> listB = doAnyThingToGetList().orElseGet(() -> new ArrayList<>());

6. Tham khảo

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm java lương cao hấp dẫn trên TopDev

Building Microservices Application – Phần mở đầu: Bức tranh tổng thể

Trong bài viết đầu tiên này, hãy cùng xem xét về bức tranh tổng thể khi xây dựng một ứng dụng Microservices

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Đây là bài viết đầu tiên trong phần Xây dựng ứng dụng với Microservices. Trong những loạt bài trước, chúng ta đã tìm hiểu qua phần lý thuyết về những “viên gạch” (building block) chủ đạo trong Microservies. Loạt bài tiếp theo sẽ hướng đến việc implement những pattern như API Gateway, Service Discovery, Circuit Breaker trong kiến trúc Microservices như thế nào.

  Cải thiện hiệu năng cho JavaScript Web Application chỉ trong vòng vài bước đơn giản
  Security Considerations khi Designing Web Applications

Đáng lẽ mình sẽ tự tay implement và giải thích về ý nghĩa của từng phần, tuy nhiên, trong thời gian research đã tìm ra được một nguồn tài liệu viết rất chuyên nghiệp và đầy đủ. Vì vậy mình sẽ dựa trên đó để viết, nhằm mang đến cái nhìn professional và đúng đắn nhất 🙂 Các bạn có thể đọc các bài viết nguyên bản tiếng Anh tại ĐÂY.

Trong bài viết đầu tiên này, hãy cùng xem xét về bức tranh tổng thể khi xây dựng một ứng dụng Microservices, sẽ gồm những thành phần (chính) nào, và cách chúng coordinate với nhau như thế nào.

1. ĐIỀU KIỆN CẦN

Điều gì là cần thiết để triển khai một số lượng lớn các microservices trong hệ thống?

Hình vẽ dưới đây, theo Martin Fowler, sẽ cho ta biết chính xác điều chúng ta cần đạt được

1

(Nguồn: http://martinfowler.com/articles/microservices.html)

Tuy nhiên, trước khi chúng ta có thể bắt đầu tung ra số lượng lớn các microservices trong hệ thống để thay thế các ứng dụng nguyên khối, có một số điều kiện tiên quyết cần được đáp ứng (hoặc ít nhất là ở mức độ nào đó). Chúng ta cần:

  • một kiến ​​trúc mục tiêu
  • một chuỗi công cụ phân phối liên tục (continues delivery)
  • một tổ chức phù hợp

Hãy xem xét một cách ngắn gọn từng điều kiện tiên quyết.

1.1. KIẾN ​​TRÚC MỤC TIÊU

Đầu tiên chúng ta cần một ý tưởng kiến ​​trúc về cách phân vùng tất cả các microservices. Ví dụ, có thể phân vùng chúng theo chiều dọc trong một số layer như:

  • Core services Xử lý logic nghiệp vụ cốt lõi
  • Composite services có thể phối hợp một số Core services để thực hiện nhiệm vụ chung hoặc tổng hợp thông tin từ một số Core services.
  • API services cung cấp chức năng cho bên ngoài

… và theo chiều ngang, chúng ta có thể áp dụng một số phân vùng theo domain. Điều này có thể dẫn đến một kiến ​​trúc như dưới đây:

2

Lưu ý: Đây chỉ là một kiến ​​trúc mẫu, kiến ​​trúc của bạn có thể hoàn toàn khác nhau. Điều quan trọng ở đây là cần phải có một kiến ​​trúc mẫu được thiết lập trước khi bắt đầu mở rộng quy mô triển khai các microservices. Nếu không, bạn có thể kết thúc trong một cảnh quan hệ thống mà chỉ trông giống như một dĩa mì spaghetti (cực kỳ rối rắm, vô tổ chức) với đặc điểm thậm chí còn tồi tệ hơn so với các ứng dụng nguyên khối hiện có.

1.2. CONTINOUS DELIVERY

Chúng ta cũng giả định rằng có một hệ thống continuous delivery tool chain để có thể triển khai các microservices của mình theo cách có hiệu quả và có thể lặp lại được, ví dụ:

3

(Nguồn: http://www.infoq.com/minibooks/emag-devops-toolchain)

1.3. TỔ CHỨC

Cuối cùng, giả định rằng chúng ta đã thông qua tổ chức của mình để tránh các vấn đề với định luật Conway:

“Organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.”

“Một công ty thiết kế hệ thống thế nào cũng sẽ làm ra những thiết kế giống y hệt với thiết kế hệ thống của chính công ty họ.”

4

(Nguồn: http://martinfowler.com/articles/microservices.html)

2. MỘT HỆ THỐNG PHỨC TẠP HƠN

Điều gì sẽ xảy ra trong một hệ thống khi chúng ta bắt đầu phân chia ứng dụng nguyên khối và thay thế chúng bằng một số lượng lớn các microservices?

Số lượng đơn vị triển khai (tức là microservice) lớn hơn. Nhiều microservices thay vì một ứng dụng nguyên khối lớn, do đó cần phải quản lý và theo dõi nhiều thành phần hơn.

Các services sử dụng và được sử dụng bởi các services khác sẽ dẫn đến một hệ thống mà nhiều services sẽ kết nối với nhau. (Xem thêm IPC)

Một số services cung cấp các API ra bên ngoài nhằm đóng gói và bảo vệ các services khác khỏi sự truy cập từ bên ngoài. (Xem thêm API Gateway)

Hệ thống sẽ động (dynamic) hơn. Các services mới được triển khai, các services cũ được thay thế hoặc loại bỏ, các instance mới của một service hiện có được khởi chạy thêm để đáp ứng tải gia tăng. Điều này có nghĩa là các services sẽ đến và đi với tần suất cao hơn nhiều so với trước đây. (Xem thêm Service Discovery)

MTBF (Mean time between failures – thời gian để có lỗi xảy ra) sẽ giảm (tức là lỗi nhiều hơn). Với rất nhiều service được triển khai và hoạt động thì xác suất xảy ra lỗi sẽ tăng lên là điều hiển nhiên.

3. NHỮNG VẤN ĐỀ ĐẶT RA

Làm thế nào tất cả các microservices được cấu hình và nó có đúng không? Xử lý cấu hình không phải là vấn đề lớn với một vài ứng dụng, ví dụ: mỗi ứng dụng lưu trữ cấu hình của riêng nó trong các tệp thuộc tính trên đĩa hoặc các bảng cấu hình trong cơ sở dữ liệu riêng của nó. Với một số lượng lớn các microservices được triển khai với nhiều instances trên nhiều máy chủ, cách tiếp cận này sẽ tạo nên vấn đề về cách quản lý cấu hình. Nó sẽ dẫn đến rất nhiều tập tin cấu hình nhỏ trên tất cả hệ thống làm cho việc duy trì và kiểm soát rất khó khăn.

Những microservices nào được triển khai và ở đâu? Bởi vì việc các microservies được triển khai với các địa chỉ máy chủ / cổng khác nhau. Với một số lượng lớn các microservices được triển khai độc lập với nhau sẽ có nhiều thay đổi liên tục trong hệ thống và điều này có thể dễ dẫn đến cơn ác mộng bảo trì nếu phải xử lý thủ công.

Cách cập nhật thông tin định tuyến (routing)? Client sử dụng các services cũng gặp các khó khăn. Cụ thể, nếu các bảng định tuyến, ví dụ như các reverse proxies hoặc các tệp cấu hình của Client, cần được cập nhật theo cách thủ công. Về cơ bản sẽ không có thời gian để chỉnh sửa thủ công các bảng định tuyến trong một hệ thống đang được phát triển liên tục với các microservices mới xuất hiện trên các địa chỉ máy chủ / cổng mới. Thời gian delivery sẽ kéo dài và rủi ro đối với các lỗi thủ công sẽ gây rủi ro về khía cạnh chất lượng và / hoặc làm cho chi phí hoạt động không cần thiết tăng lên.

Làm thế nào để ngăn chặn chuỗi sự cố xảy ra (chain of failures)? Vì các microservices sẽ được kết nối với nhau, cần phải chú ý đặc biệt để tránh các chuỗi sự cố. Nếu không được xử lý đúng thì một lỗi ở một microservies nào đó cũng có thể dẫn đến việc ngừng trệ toàn bộ cả hệ thống.

Làm cách nào để xác minh rằng tất cả các services đều đang hoạt động? Việc theo dõi trạng thái của một vài ứng dụng khá đơn giản nhưng làm cách nào để chúng ta xác minh rằng tất cả các microservices đều khỏe mạnh và sẵn sàng nhận request?

Làm cách nào để theo dõi các thông điệp giữa các services? Điều gì xảy ra nếu team bắt đầu nhận được khiếu nại về một số quá trình xử lý không thành công? Microservice nào là nguyên nhân gốc rễ của vấn đề? Làm thế nào ta có thể phát hiện ra rằng việc xử lý, ví dụ, đơn hàng 12345 bị kẹt vì không thể truy cập vào microservice A hoặc cần phê duyệt thủ công trước khi microservice B có thể gửi thông báo xác nhận liên quan đến đơn hàng đó?

Làm thế nào để đảm bảo rằng chỉ các API-services được đưa ra bên ngoài? Ví dụ: làm cách nào để tránh truy cập trái phép từ bên ngoài vào các microservices nội bộ?

Làm cách nào để bảo mật các API-services? Không phải là câu hỏi mới hoặc cụ thể liên quan đến microservices nhưng vẫn rất quan trọng để bảo đảm cho các microservices an toàn khi đưa ra ngoài.

4. CÁC THÀNH PHẦN CHÍNH TRONG MICROSERVICES

Để giải quyết các câu hỏi này, chúng ta sẽ cần các thành phần sau trong một hệ thống microservies:

Central Configuration server. Thay vì cấu hình cục bộ cho mỗi đơn vị triển khai (tức là microservice), chúng ta cần quản lý cấu hình tập trung. Chúng ta cũng cần một configuration API để các microservices có thể sử dụng để lấy thông tin cấu hình.

Service Discovery server. Thay vì theo dõi thủ công những microservices nào được triển khai hiện tại và trên máy chủ và cổng nào, chúng ta cần chức năng Service Discovery cho phép microservices tự đăng ký khi khởi động thông qua API.

Dynamic Routing and Load Balancer. Với chức năng service discovery, các thành phần định tuyến có thể sử dụng discovery API để tra cứu nơi mà microservice được yêu cầu được triển khai và các thành phần cân bằng tải có thể quyết định định tuyến yêu cầu tới instance nào nếu nhiều instance được triển khai cho một service được yêu cầu.

Circuit Breaker. Để tránh chuỗi sự cố, cần phải áp dụng Circuit Breaker pattern, bạn có thể đọc thêm trong cuốn sách Release It! hoặc bài đăng trên blog của Fowler – Circuit Breaker.

Monitoring. Vì đã có circuit breakers, chúng ta có thể bắt đầu theo dõi trạng thái của chúng và thu thập số liệu thống kê thời gian chạy từ chúng để có được một bức tranh về tình trạng sức khỏe của hệ thống.

Centralized log analysis. Để có thể theo dõi messages và phát hiện khi chúng bị kẹt (stuck), chúng ta cần một chức năng phân tích log tập trung có khả năng tiếp cận với máy chủ và thu thập các tệp log mà mỗi services microservice tạo ra. Chức năng phân tích log lưu trữ thông tin log này trong cơ sở dữ liệu trung tâm và cung cấp khả năng tìm kiếm và dashboard. Lưu ý : Để có thể tìm thấy các messages liên quan, điều quan trọng là tất cả các microservices phải sử dụng id đồng nhất trong các log message.

Edge Server. Để đưa các API services ra bên ngoài và để ngăn chặn truy cập trái phép vào các microservices nội bộ, chúng ta cần một edge server nơi tất cả request bên ngoài đi qua. Một edge server có thể tái sử dụng khả năng định tuyến động và cân bằng tải dựa trên service discovery được mô tả ở trên. Edge server sẽ hoạt động như một proxy ngược chủ động mà không cần cập nhật thủ công khi hệ thống nội bộ thay đổi.

OAuth 2.0 protected API’s Để bảo vệ các API services được expose ra bên ngoài, quy trình của OAuth 2.0 có thể như sau:

  • Một component mới có thể đóng vai trò như một Máy chủ ủy quyền (OAuth Authorization Server)
  • Các API services sẽ đóng vai trò như các Máy chủ tài nguyên (OAuth Resource Server)
  • Các Client bên ngoài gọi đến API services với tư cách là OAuth Clients
  • Edge server sẽ làm việc như một OAuth Token Relay, có nghĩa là:
    • Nó sẽ hoạt động như một OAuth Resource Server
    • Nó sẽ chuyển các OAuth Access Tokens có trong request bên ngoài đến các API services

5. MÔ HÌNH THAM CHIẾU

5

Lưu ý: Để giảm độ phức tạp, các tương tác giữa microservices và các services hỗ trợ không được vẽ.

6. BƯỚC TIẾP THEO

Trong các bài viết sắp tới, chúng ta sẽ lần lượt tìm hiểu về từng thành phần trong mô hình tham chiếu.

Series này là phần tiếp theo series Microservices: Từ Thiết Kế Đến Triển Khai, tập trung vào việc hiện thực hóa các khái niệm đã mô tả ở phần lý thuyết. Hi vọng sẽ giúp ích được cho các bạn khi làm quen với microservies. Các bạn có thể tham khảo thêm về phần Architecture căn bản ở đây nhé.

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT Job hấp dẫn trên TopDev

Tại sao nên sử dụng controller as trong AngularJS?

Tại sao nên sử dụng controller as trong AngularJS

Bài viết được sự cho phép của tác giả Tino Phạm

Cho tới thời điểm này cú pháp Controller As được nhiều người khuyến khích sử dụng.

Tại sao vậy? có gì lợi hại hơn khi dùng Controller As?

  Inversion of Control nguyên lý của các nguyên lý

  Inversion of Control và Dependency Injection

Trước hết hãy xem 2 ví dụ sau đây, một cái dùng Controller và một dùng Controller As

  • Ví dụ 1 – dùng $Scope bình thường

  • Ví dụ 2 – dùng Controller as

Với cách dùng Controller as chúng ta thấy code dễ hiểu hơn. Đó là cái thứ nhất.

Khi bạn dùng cú pháp controller as thì Angular controller sẽ tạo ra một đối tượng và gán đối  tượng này vào $scope với tên mà bạn đã đặt trước đó. Ở đây các đối tượng được tạo ra là: main, another, yet.

Ảnh từ angular.org

Với $scope bạn sẽ gặp phải các vấn đề khi dùng controller lồng nhau, và các controller đó có nhưng thuộc tính giống nhau. Vậy bạn sẽ phải nhớ từng thuộc tính và cẩn thận khi dùng nó. Với Controller as, bạn sẽ có một cách viết rõ ràng và an toàn hơn khi sử dụng.

Khi bạn cần truy xuất các thuộc tính của $scope cha (parent scope), bạn sẽ không cần làm thế này:

mà bạn sẽ viết thế này

Bạn thấy không, chúng ta không cần phải viết dài dòng: $scope.$parent.$parent. Việc này khiến bạn phải cẩn thận và phải nhớ là có bao nhiêu $parent để có thể lấy chính xác dữ liệu mà bạn muốn, code của bạn xấu xí khó nhìn và cũng khó hiểu.

Tôi thường thấy mọi người dùng Controll as vm. Tại sao lại dùng biến vm? nó có khác biệt gì khi tôi đặt tên khác không?

Câu trả lời là bạn hoàn toàn CÓ THỂ đặt tên gì bạn muốn và nó KHÔNG KHÁC biệt gì cả. Nó giống nhau cả.

Nhưng, tại sao nhiều người hay dùng vm?

Bởi vì nó ngắn gọn và thường nó được hiểu như khái niệm view-model (nó thật sự không chính xác lắm nhưng theo nhiều người thường quy ước như vậy). Hãy xem ví dụ sau đây để hiểu thêm một vấn đề nữa.

Xem ví dụ trên, chúng ta có customers.customers bên trong ng-repeat. Đoạn code này làm bạn khó hiểu đúng không.

Vậy thì tôi sẽ đặt tên cho controller as chẳng hạn như: customerCtrl hoặc là custCtrl.

Đây là vấn để sở thích và phóng cách riêng của mỗi người nên bạn hoàn toàn có thể làm thế.

Tại sao lại dùng var vm = this?

Vì từ khóa this  được hiểu khác nhau trong từng ngữ cảnh (context) cho nên việc dùng nó đôi khi sẽ gặp vài vấn đề không theo ý muốn.

Vậy có phải tôi không cần dùng đến $scope nữa không?

Không phải hoàn toàn, vì chúng ta vẫn cần dùng đến $scope trong các trường hợp như: $scope.$on(), $scope.$watch(), $scope.apply(),….

Tóm lại, việc dùng controller as vì những lý do sau đây:

  1. Giúp code dễ hiểu và an toàn hơn. Nhất là trường hợp controller lồng nhau.
  2. Chúng ta dùng vm thay cho this là vì:
    1. this được hiểu khác nhau trong từng ngữ cảnh (context).
    2. vm viết ngắn gọn nhưng chúng ta vẫn hiểu được đó là một dạng view-model.

Bài viết xin kết thúc tại đây. Hy vọng được các bạn chia sẽ và đóng góp thêm ý kiến.

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Hiện thực WebSocket với Spring framework

Hiện thực WebSocket với Spring framework

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

WebSocket là một trong các loại Socket, nói nôm na cho các bạn dễ hình dung về WebSocket thì nó giúp chúng ta có thể tạo kết nối 2 chiều giữa server side và client side trong một web application bất kỳ. Một khi kết nối đã được thiết lập thì client và server có thể trao đổi các thông tin với nhau, client có thể gửi message cho server và ngược lại server cũng vậy. Khác với HTTP connection thì chỉ có client mới có thể gửi request tới server, server trả về response, server không thể tự gửi message tới bất kỳ client nào. WebSocket thường được sử dụng trong các ứng dụng web đòi hỏi tính realtime của một chức năng nào đó. Trong bài viết này, mình sẽ hướng dẫn các bạn cách hiện thực WebSocket trong một web application với Spring framework các bạn nhé!

  10 Java Web Framework tốt nhất
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

Đầu tiên, mình sẽ tạo mới một Spring Boot project:

Hiện thực WebSocket với Spring framework

với Web và WebSocket dependency như sau:

Hiện thực WebSocket với Spring framework

để làm ví dụ.

Kết quả:

Hiện thực WebSocket với Spring framework

Tạo mới WebSocket server

Để khởi tạo WebSocket server với Spring WebSocket, trước tiên, các bạn cần phải nắm một số khái niệm như sau:

Đầu tiên là về Message Broker, nó là một message-oriented middleware server đứng ở giữa để delivery message từ các request tới các topic theo cơ chế pub-sub hoặc queue theo cơ chế point-to-point. Có nghĩa là thay vì các application gửi thẳng message tới topic hoặc queue mà các bạn thường thấy khi làm việc với Message Queue thì với Message Broker, các message phải đi qua Message Broker này. Spring sử dụng Message Broker để hiện thực WebSocket behind the sense đó các bạn!

Cái thứ hai là mình sẽ nói về STOMP. STOMP là gì? Nó là viết tắt của từ Streaming Text Oriented Messaging Protocol, dịch ra thì STOMP là một giao thức tin nhắn hướng văn bản, được sử dụng để client và server sau khi đã connect được với nhau, sử dụng để trao đổi thông tin. Spring cũng hỗ trợ giao thức này trong việc truyền thông tin giữa client và server với WebSocket đó các bạn.

OK, giờ chúng ta sẽ khai báo để tạo mới một WebSocket server các bạn nhé!

Các bạn cần tạo mới một class để cấu hình cho WebSocket. Class này sẽ implement interface WebSocketMessageBrokerConfigurer và được annotate với annotation @EnableWebSocketMessageBroker nha các bạn:

package com.huongdanjava.springboot.websocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

}

Tất nhiên, là nó cũng cần được annotate với annotation @Configuration để Spring Boot tự động scan nữa!

Có 2 phương thức mà chúng ta cần implement trong class WebSocketConfiguration này là configureMessageBroker() và registerStompEndpoints(). Phương thức configureMessageBroker() với tham số là class MessageBrokerRegistry cho phép chúng ta có thể cấu hình Message Broker với phương thức enableSimpleBroker():

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}

Tham số của phương thức enableSimpleBroker() là tên endpoint để các client có thể subscribe và nhận message từ server.

Trong phương thức configureMessageBroker() trên, mình cũng sử dụng thêm phương thức setApplicationDestinationPrefixes() để định nghĩa prefix cho các destination mà client sẽ gửi message tới WebSocker server. Các bạn nếu đã làm việc với RESTful Web Service sử dụng Spring MVC thì có thể hình dung mục đích của phương thức này giống như các bạn định nghĩa một request mapping trong Controller ở class level. Những method định nghĩa các request URL sẽ có prefix là value của request mapping này.

Phương thức registerStompEndpoints() với tham số là class StompEndpointRegistry thì cũng giống như khi định nghĩa các request URL trong RESTful Web Service, giúp chúng ta định nghĩa những endpoint mà client sẽ sử dụng để gọi và kết nối tới WebSocket. Chúng ta sử dụng phương thức addEndpoint() của class StompEndpointRegistry để thêm các endpoint mà các bạn muốn. Ví dụ mình định nghĩa một endpoint như sau:

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello");
}

Một số trình duyệt có thể sẽ không hỗ trợ WebSocket connection ví dụ như chế độ ẩn danh của trình duyệt Chrome chẳng hạn. Trong trường hợp này, các bạn có thể gọi thêm method withSockJS() để sử dụng các giải pháp thay thế khác như xhr-streaming, xhr-polling thay vì kết nối WebSocket mặc định.

Nội dung class WebSocketConfiguration của mình lúc này như sau:

package com.huongdanjava.springboot.websocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}

Để handle message từ client gửi tới endpoint mà chúng ta vừa mới configure ở trên “/hello”, các bạn có thể tạo mới một controller MessageController với nội dung như sau:

package com.huongdanjava.springboot.websocket;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class MessageController {

@MessageMapping("/hello")
@SendTo("/topic/messages")
public String send(String username) {
return "Hello, " + username;
}
}

Giống như controller trong Spring MVC, các bạn có thể annotate class handle message từ client với annotation @Controller nhưng thay vì sử dụng annotation @RequestMapping trong method handle message, chúng ta sử dụng annotation @MessageMapping với value là giá trị của endpoint mà chúng ta đã cấu hình trong class WebSocketConfiguration, ví dụ của mình là “/hello”.

Sau khi method xử lý business logic và trả về kết quả, kết quả này sẽ được gửi tới destination mà client đã subscribe, được khai báo trong annotation @SendTo.

Bây giờ, nếu các bạn chạy ứng dụng, xem log message, các bạn sẽ thấy WebSocket server sẽ start và sẵn sàng nhận kết nối từ phía client như sau:

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0)

2021-06-05 11:36:45.108 INFO 38061 --- [ main] c.h.s.w.SpringBootWebsocketApplication : Starting SpringBootWebsocketApplication using Java 15.0.1 on Khanhs-MBP with PID 38061 (/Users/khanh/Documents/workspace-spring-tool-suite-4-4.9.0.RELEASE/spring-boot-websocket/target/classes started by khanh in /Users/khanh/Documents/workspace-spring-tool-suite-4-4.9.0.RELEASE/spring-boot-websocket)
2021-06-05 11:36:45.110 INFO 38061 --- [ main] c.h.s.w.SpringBootWebsocketApplication : No active profile set, falling back to default profiles: default
2021-06-05 11:36:46.683 INFO 38061 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-06-05 11:36:46.694 INFO 38061 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-06-05 11:36:46.694 INFO 38061 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2021-06-05 11:36:46.860 INFO 38061 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-06-05 11:36:46.860 INFO 38061 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1609 ms
2021-06-05 11:36:47.306 INFO 38061 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-06-05 11:36:47.307 INFO 38061 --- [ main] o.s.m.s.b.SimpleBrokerMessageHandler : Starting...
2021-06-05 11:36:47.307 INFO 38061 --- [ main] o.s.m.s.b.SimpleBrokerMessageHandler : BrokerAvailabilityEvent[available=true, SimpleBrokerMessageHandler [org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry@6a1ef65c]]
2021-06-05 11:36:47.308 INFO 38061 --- [ main] o.s.m.s.b.SimpleBrokerMessageHandler : Started.
2021-06-05 11:36:47.319 INFO 38061 --- [ main] c.h.s.w.SpringBootWebsocketApplication : Started SpringBootWebsocketApplication in 2.769 seconds (JVM running for 3.982)
2021-06-05 11:36:47.320 INFO 38061 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state LivenessState changed to CORRECT
2021-06-05 11:36:47.321 INFO 38061 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state ReadinessState changed to ACCEPTING_TRAFFIC
2021-06-05 11:37:47.023 INFO 38061 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]

Tiếp theo, chúng ta sẽ code phần client để xem WebSocket hoạt động như thế nào nhé các bạn!

Tạo mới client kết nối tới WebSocket server

Mình sẽ viết code HTML, JavaScript để giả lập việc gửi message từ client tới server, và cả việc server gửi message tới client như thế nào.

Mình sẽ sử dụng WebJars để thêm JQuerySocketJS client và Stomp WebSocket dependencies như sau:

<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.4</version>
</dependency>

JQuery dùng để viết code Javascript dễ dàng hơn, SockJS để làm việc với WebSocket connection còn Stomp WebSocket thì để chúng ta làm việc với STOMP message đó các bạn!

Mình sẽ tạo mới một trang HTML cho phép chúng ta nhập tên user, nhấn nút gửi tới WebSocket server, và một nơi để hiển thị kết quả trả về từ WebSocket server.

Hiện thực WebSocket với Spring framework

Nội dung của tập tin index.html trong thư mục src/main/resources/static như sau:

<!DOCTYPE html>
<html>
<head>
<title>Hello WebSocket</title>
<script src="/webjars/jquery/dist/jquery.min.js"></script>
<script src="/webjars/sockjs-client/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/stomp.min.js"></script>
<script src="/app.js"></script>
</head>
<body>
<div id="main-content">
<div>
<form>
<div>
<label>What is your name?</label> 
<input type="text" id="name" placeholder="Your name here...">
</div>
<button id="send" type="submit">Send</button>
</form>
</div>
</div>
<div>
<label>Message from server: </label><span id="message"></span>
</div>
</body>
</html>

Tập tin app.js cũng trong thư mục src/main/resources/static có nội dung như sau:

var stompClient = null;

$(document).ready(function() {
connect();
});

function connect() {
var socket = new SockJS('/hello');
stompClient = Stomp.over(socket);
stompClient.connect({}, function() {
console.log('Web Socket is connected');
stompClient.subscribe('/topic/messages', function(message) {
$("#message").text(message.body);
});
});
}

$(function() {
$("form").on('submit', function(e) {
e.preventDefault();
});
$("#send").click(function() {
stompClient.send("/app/hello", {}, $("#name").val());
});
});

Nếu các bạn biết một chút về JQuery thì sẽ hiểu code của mình có nghĩa là: khi browser đã load nội dung của trang index.html, web của mình sẽ tự động connect tới WebSocket server sử dụng thư viện SockJS client và sử dụng thư viện Stomp WebSocket để gửi STOMP message. Đối tượng Stomp Client sẽ subscribe vào “/topic/messages” để nhận message từ WebSocket server.

Stomp Client cho phép chúng ta có thể gửi một STOMP message tới WebSocket server sử dụng endpoint “/app/hello” với giá trị chúng ta nhập trong textbox.

Mỗi khi nhận message từ WebSocket server thì giá trị trong phần body của STOMP message này sẽ được hiển thị.

Kết quả khi mình chạy ứng dụng, nhập Khanh vào textbox và nhấn nút Send như sau:

Hiện thực WebSocket với Spring framework

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Điều hướng trong Node.js

Điều hướng trong Node.js

Bài viết được sự cho phép của smartjob.vn

Các bạn mất 20 phút thực hành và đi tới phần này để hiểu hơn về cách hoạt động khi có 1 request tới và điều hướng trả về file Html nào .Ví dụ như sau khi bạn nhập trình duyệt : http://127.0.0.1/about.html thì server trả về cho bạn nội dung có trong file about.html

  10 Công ty hàng đầu thế giới sử dụng Node.js
  Cách tạo một Docker đơn giản cho Node.JS

Tạo file và thư mục tại bất kỳ đâu bạn muốn dưới đây demo mình để ở  ổ E như hình  dưới:

Cấu trúc thư file folder như sau:  public   ,  dieuhuong.js  , about.html ,  home.html

Nội dung các file như sau :

Trên file trên sẽ đọc request  của url  lấy nội dung file trong thư mục public truyền vào biến data respone về trình duyệt.

about.html

home.html

Sau đó mở CMD  tới thư mục chứa file dieuhuong.js  thự thi tiến trình bằng cách gõ lệnh node dieuhuong.js  ở đây mình để ở thư mục     E:\dieuhuong_node.js_smartjob.vn

Sau đó mở trình duyệt gõ địa chỉ và kiểm tra:  http://127.0.0.1/about.html    http://127.0.0.1/home.html

Các bạn  có thể thêm các file smartjob.html hay  file khác trong html và thứ request . Trên đây là hướng dẫn cơ bản nhất code thuần node js để diều hướng và gửi về  nội dung file html  để các bạn có thể hình dung ra cách hoạt động . Sau này việc điều hướng Route sẽ sử dụng thư viện express trong node js để diều hướng với nhiều phân cấp chức năng hơn .

Chúc các bạn thực hành thành công mọi thắc mắc các bạn có thể liên hệ qua Skype : nguyenanhdung90.

Bài viết gốc được đăng tải tại smartjob.vn

Có thể bạn quan tâm:

Xem thêm IT Jobs Developer hấp dẫn trên TopDev

Hướng dẫn Angular 2 cho người mới bắt đầu – Phần 3

Hướng dẫn Angular 2 cho người mới bắt đầu – Phần 3

Bài viết được sự cho phép của tác giả Tino Phạm

Ở phần 2, bạn đã tạo được một ứng dụng với Angular 2 + Typescript. Tuy nhiên, nó không có gì ngoài hiển thị dòng chữ “My First Angular 2 App”. Trong phần này, mình sẽ cố gắng giải thích thêm về các bước mà chúng ta đã thực hiện ở phần 2.

  "Muốn đi nhanh phải dựa vào dev, muốn đi nhanh hơn nữa phải dựa vào khách hàng"

  8 lợi thế khi sử dụng Polymer so với Angular và React
  1. File tsconfig.json
    File tsconfig.json là file cấu hình cho trình biên dịch của Typescript (Typescript compiler configuration). Nghĩa là, chúng ta viết code Typescript ( *.ts ) nhưng khi chạy ứng dụng thì browser sẽ đọc nội dung file ( *. js ). Ví dụ: main.ts => sẽ có main.jsmain.js.map được sinh ra.Các files main.jsmain.js.map được Typescript compiler (tsc) tạo ra khi chúng ta gọi lệnh npm start.Vậy khi Typescript compiler chạy, nó sẽ đọc nội dung file tsconfig.json để biết được làm thế nào để biên dịch từ Typescript sang Javascript.

    • target: “es5”  => sử dụng phiên bản ECMAScript 2009 (ES6: ECMAScript 2015). Bạn có thể thay đổi nếu muốn dùng ES6 để biên dịch.
    • module: “system” => chỉ ra làm thế nào để các modules được load lên khi làm việc với các file riêng lẽ. Ở đây sử dụng system. Ngoài ra còn các patterns: CommonJS, AMD, UMD
    • sourceMap: true => cho phép tạo ra file *.map tương ứng.
    • moduleResolution: “node” => cách này chúng ta có thể load modules từ thư mục node_modules.
    • emitDecoratorMetadata và experimentalDecorators: true => enable sử dụng decorators.
    • noImplicitAny: false => disable thông báo lỗi khi method hay property không có kiểu.
    • exclude: định nghĩa những thư mục, những files mà sẽ bị loại ra hay  bỏ ra khi biên dịch.
  2. File typings.json
    Nhiều thư viện (Library) Javascript mở rộng thêm các tính năng mới và cú pháp mới cho môi trường Javascript. Nhưng, trình biên dịch của Typescript (Typescript compiler) không nhận ra được và nó sẽ quăng ra lỗi.
    File typings.json sẽ được dùng để giải thích cho những định nghĩa mà bạn dùng để mở rộng Javascript trong ứng dụng của bạn.

    • core-js: giúp cho các trình duyệt chỉ hỗ trợ ES5 trở xuống có thể hiểu được những code viết bằng ES6.
    • jasmine: sử dụng Jasmine test framework.
    • node: dùng cho code mà nó tham chiếu đến các đối tượng trong môi trường NodeJS
  3. File package.json
    package.json lưu lai thông tin của ứng dụng, cùng với thông tin của những gói thư viện mà ứng dụng của bạn đang dùng. Khi chúng ta gõ lệnh: npm install thì những Library được định nghĩa trong package.json sẽ được tải về và cài đặt.
  4. Terminal trong VS Code và Command Line (cmd) trong window
    Trong Visual Studio Code bạn có thể sử dụng Terminal thay cho Command Line của window. Sẽ tiện lợi hơn cho bạn không cần mở nhiều windows khi làm việc.
  5. Một số lệnh cần thiết khi build và run ứng dụng
    • npm install: dùng để cài đặt tất cả các gói được định nghĩa sẵn  trong file package.json
    • npm install tên_package -g –save: để cài đặt từng gói thư viện mà bạn cần và lưu thông tin vào package.json. Cách này dùng khi bạn build ứng dụng của bạn ban đầu. Khi gửi ứng dụng của bạn cho người khác bạn sẽ bỏ qua (bỏ ra) thư mục node_modules. Đây là thư mục chứa những gói thư viện được dùng cho ứng dụng của bạn. Vậy, những người khác sẽ phải gõ lệnh: npm install để tải về và cài đặt những gói được lưu trong package.json
    • tsc: lệnh này dùng để biên dịch file *.ts thành *.js
    • npm run lite: chạy lite server
    • npm start: lệnh này sẽ tự động thực thi lệnh tsc và npm run lite
    • ctrl + c : stop lite server
    • ctrl + `: mở chế độ Terminal trong VS Code

Lưu ý: để sử dụng được lệnh tsc bạn phải update typescript 2.0 và trong file tsconfig.json bạn sửa thông tin:
“target”: “es6“,
“module”: “commonjs

Trong phần 4, chúng ta sẽ viết thêm các tính năng mới và mở rộng ứng dụng.

Tham khảo:
1. http://www.typescriptlang.org/docs/handbook/compiler-options.html
2. https://angular.io/docs/ts/latest/guide/typescript-configuration.html
3. https://www.tutorialspoint.com/angular2/angular2_environment.htm

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Cấu trúc trang HTML cơ bản

Cấu trúc trang HTML cơ bản

Bài viết được sự cho phép của tác giả Kien Dang Chung

Quá trình học lập trình thường khá dài và hầu hết mọi người đều muốn nhanh chóng bước vào các bài lý thuyết lập trình và thực hành các ví dụ thực tế. Những bài viết đầu tiên một khóa học lập trình web chủ yếu giới thiệu các thông tin xoay quanh ngôn ngữ, các thuật ngữ liên quan tuy nhiên cũng rất quan trọng bởi khi bạn đã nắm được HTML5 là gì? thì việc học các cấu trúc, các thẻ html chỉ là công cụ để xây dựng website mà thôi. Có rất nhiều bạn đã vào nghề lập trình web rất lâu nhưng không hiểu rõ bản chất HTML là gì hay còn mơ hồ về siêu văn bản, tại sao lại phải sử dụng HTML?… mà chỉ nhăm nhăm muốn code ngay. Những kiến thức cơ bản là nền tảng để phát triển tư duy công việc sau này, bạn không chỉ là một người lập trình (coder) mà biết đâu bạn có thể trở thành một người nghiên cứu, một người phát triển những ngôn ngữ, những công nghệ mới? Dài dòng một chút những chia sẻ về nghề và giờ là lúc chúng ta cùng đi vào tìm hiểu kiến thức HTML cơ bản. Theo truyền thống, một ví dụ HTML đầu tiên – Chào mừng đến với khóa học HTML cơ bản, một ví dụ đơn giản cho cái nhìn đầu tiên về HTML.

  HTML5 khác HTML như thế nào?

1. Ví dụ HTML đầu tiên – Chào mừng đến với khóa học HTML cơ bản

Trong suốt khóa học HTML cơ bản chúng ta sẽ sử dụng hai công cụ để tiện demo và show code cho các bạn là Sublime Text và JsFiddle. Ok, bạn hãy mở Sublime Text tạo một file hello-world.html với nội dung sau:

<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8>
    <title>Ví dụ HTML đầu tiên - Chào mừng đến với Khóa học HTML cơ bản</title>
  </head>
  <body>
    <h1 class="text-success">Khóa học HTML cơ bản</h1>
    <p>Chào mừng bạn đến với khóa học HTML cơ bản từ website allaravel.com, chúng ta sẽ cùng nhau tìm hiểu từ những vấn đề cơ bản nhất của HTML và những gì mới nhất trong phiên bản HTML5.</p>
  </body>
</html>

Kết quả khi chạy file hello-world.html chúng ta được như sau:

[jsfiddle url=”https://jsfiddle.net/allaravel/808ahvjg/” height=”200px” include=”result,html,js” font-color=”39464E” menu-background-color=”FFFFFF” code-background-color=”f3f5f6″ accent-color=”1C90F3″]

Chú ý, phần kết quả thay vì chụp lại nội dung hiển thị trên trình duyệt thì chúng ta sẽ mặc định dùng JsFiddle để xem được nhanh chóng và trực quan.

Ví dụ HTML đầu tiên

Trong ví dụ HTML đầu tiên này, chúng ta tạm coi như đã biết code HTML, các phần tiếp theo sẽ diễn giải những gì đã sử dụng. Mã HTML ở trên khá nhiều nhưng khi xem trên trình duyệt, nội dung lại rất ít, còn toàn văn bản vì HTML là ngôn ngữ đánh dấu siêu văn bản, nó cho trình duyệt biết chỗ nào phải hiển thị như là tiêu đề (thẻ <h1>) và chỗ nào là đoạn văn mô tả (thẻ <p>).

2. Các khái niệm HTML cơ bản

Trong ví dụ HTML đầu tiên nếu bạn mới bắt đầu học HTML cơ bản, bạn sẽ thấy hơi hoa mắt chút nhưng đảm bảo rằng sau khi được giới thiệu các khái niệm HTML cơ bản, bạn sẽ làm chủ được đoạn code này dễ dàng.

  HTML là gì?

Cấu phần của HTML element

2.1 HTML element vs thẻ HTML

Để ý trong ví dụ HTML đầu tiên, có rất nhiều các chuỗi ký tự được mở đầu bằng < hoặc </ và kết thúc bằng >. Mỗi chuỗi ký tự đó được gọi là thẻ HTML, ví dụ <title><h1>… chúng ta gọi đây là thẻ title hoặc thẻ h1. HTML element là các thành phần của HTML, ví dụ <h1>Khóa học HTML cơ bản</h1> là thành phần h1 của HTML, nó được bắt đầu bằng thẻ mở <h1> và kết thúc bằng thẻ đóng </h1>. Vậy mỗi thành phần HTML sẽ bao gồm:

  • Thẻ mở bắt đầu bằng < và kết thúc bằng >, ví dụ <h1><p>.
  • Thẻ đóng bắt đầu bằng </ và kết thúc bằng >, ví dụ </h1></p>.

Nội dung giữa thẻ mở và thẻ đóng của một HTML element sẽ là nội dung được hiển thị trên trình duyệt, thẻ mở và thẻ đóng sẽ “đánh dấu” (markup) để trình duyệt hiểu được cụm từ “Khóa học HTML cơ bản” là tiêu đề loại lớn nhất (h1 – Heading 1).

Trong thực tế, chúng ta cũng không cần quá phân biệt HTML element với HTML tag (thẻ HTML) mà có thể gọi chung là thẻ h1, thẻ p, thẻ body… chúng ta thống nhất trong suốt Khóa học HTML cơ bản, khi nói đến thẻ HTML chúng ta coi đó là HTML element.

Như vậy trong ví dụ trên chúng ta có các thẻ HTML là html, head, title, meta, body, h1, p.

2.2 Thuộc tính của thẻ html

Trong thẻ <h1 class=”text-success”>Khóa học HTML cơ bản</h1>, chuỗi class=”text-success” là thuộc tính của thẻ HTML, nó cung cấp thông tin thêm cho thẻ HTML. Ở đây có thể có nhiều các thẻ h1 và chúng ta phân biệt các thẻ này bằng thuộc tính class, tức là các thẻ h1 có thuộc tính class là text-success sẽ được nhóm chung vào một nhóm để có thể tô màu, tăng giảm kích thước chữ, chọn font chữ sau này.

Thuộc tính của một thẻ HTML có những tính chất như sau:

  • Tất cả các thẻ HTML đều có có thể các thuộc tính.
  • Các thuộc tính cung cấp thêm các thông tin cho thẻ HTML.
  • Các thuộc tính luôn được đưa vào thẻ mở trong thẻ HTML.
  • Thuộc tính luôn đi theo cặp tên thuộc tính/giá trị thuộc tính, ví dụ class=”text-success”.

Thuộc tính class của thẻ h1 trong ví dụ trên chưa thực sự rõ ý nghĩa sử dụng do chúng ta chưa sử dụng đến thẻ này, chúng ta cùng xem một số ví dụ tiếp theo bạn sẽ hiểu rõ hơn thuộc tính trong HTML sử dụng làm gì?

Ví dụ 1: thuộc tính src của thẻ  giúp chỉ rõ đường dẫn đến ảnh cần hiển thị

<img src="public/news/anh-dep.jpg"

Ví dụ 2: thuộc tính style giúp “trang điểm” cho thẻ HTML, ví dụ này chúng ta sẽ tô màu đỏ cho thẻ h1

<h1 style="color:red">Khóa học HTML căn bản</h1>

Tham khảo việc làm lập trình viên HTML lương cao trên TopDev

3. Cấu trúc căn bản một trang HTML

Như vậy bạn đã nắm được một số khái niệm căn bản trong HTML và giờ là lúc xem lại code của ví dụ HTML đầu tiên, nó đã bớt phức tạp hơn. Trong đầu bạn hiện lại có những câu hỏi tiếp theo, các thẻ h1, p thì rõ ý nghĩa của nó rồi, còn lại một đống thẻ HTML khác để làm gì? Khoan đi vào chi tiết, bạn chỉ cần nhớ rằng, đây là cấu trúc chung của một trang HTML.

<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8>
    <title>Tiêu đề của trang</title>
  </head>
  <body>

  </body>
</html>

Đầu tiên, trước khi khai báo các thẻ khác trong HTML chúng ta cần khai báo dạng tài liệu bằng thẻ <!DOCTYPE>, cách khai báo này là khác nhau cho các phiên bản HTML.

Trong HTML4 chúng ta khai báo nội dung tiếp theo viết theo tiêu chuẩn HTML4 bằng cách đưa cú pháp sau vào dòng đầu tiên của mã nguồn:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

Với HTML5, cách khai báo đơn giản hơn do HTML5 không còn dựa trên SGML nên không phải khai báo DTD:

<!DOCTYPE html>

Tiếp theo, toàn bộ nội dung trong thẻ <htm> chính là nội dung siêu văn bản. Trong nội dung này chúng ta nhìn bố cục sẽ có hai phần:

  • Phần đầu được khai báo bằng thẻ <head>. Trong phần này, chúng ta có thể khai báo một số vấn đề như:
    • Tiêu đề của văn bản
    • Văn bản sử dụng bảng mã ký tự nào
    • Các thông tin thêm cho văn bản chính (metadata) như thông tin tác giả, mô tả bài viết, từ khóa bài viết…
    • Các file css, javascript có thể chèn vào tại đây.
  • Phần nội dung được khai báo bằng thẻ <body>, đây là phần sẽ hiển thị trên trình duyệt.

Về bố cục một trang HTML bạn có thể nắm được như vậy, khi viết một trang HTML mới, bạn có thể sao chép cấu trúc trang HTML cơ bản này. Tiếp theo chúng ta cùng tìm hiểu cụ thể một số thẻ HTML có trong bố cục.

Thẻ title

Xác định tiêu đề của văn bản, tiêu đề này sẽ được hiển thị trong phần tab của trình duyệt giúp chúng ta nhanh chóng biết được siêu văn bản (trang web) nào đang được mở khi một trình duyệt mở nhiều trang một lúc.

Thẻ title HTML

Thẻ meta

Định nghĩa các thông tin thêm (metadata) cho tài liệu, các thông tin này bao gồm thông tin về tác giả, thông tin mô tả nội dung, thông tin từ khóa… có thể nói rằng thẻ meta mô tả thông tin của thông tin. Các thông tin của thẻ meta không hiển thị trên trình duyệt nhưng các bộ máy khác có thể sử dụng chúng, ví dụ bộ máy tìm kiếm Google, Bing, Facebook sẽ sử dụng các thông tin từ thẻ meta để phân loại nội dung trang web. Có duy nhất thẻ meta nhưng lại khai báo được nhiều các thông tin về metadata là do chúng ta có thể sử dụng các thuộc tính khác nhau:

  <meta charset="UTF-8">
  <meta name="description" content="HTML5 là phiên bản mới nhất của ngôn ngữ HTML, những bài viết trong khóa học HTML5 cơ bản giúp bạn xây dựng website nhanh chóng.">
  <meta name="keywords" content="HTML5,khóa học HTML,HTML cơ bản">
  <meta name="author" content="FirebirD[Kiên Đặng]">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

Thẻ meta đầu tiên thiết lập bảng mã sử dụng, UTF-8 (8-bit Unicode Transformation Format – Định dạng chuyển đổi Unicode 8-bit) là bộ mã hóa ký tự dành cho Unicode, nó có thể tương thích ngược với bảng mã ASCII. UTF-8 là bộ mã phổ biến và thông dụng cho các nội dung điện tử như các file tài liệu, thư điện tử, trang web và các phần mềm xử lý văn bản. Với phiên bản HTML4 trở xuống, để thiết lập bảng mã ký tự phải sử dụng thuộc tính http-equiv kết hợp với content.

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

Ba thẻ meta tiếp theo mô tả thông tin về trang web, nó giúp các bộ máy tìm kiếm như Google, Bing phân loại nội dung, các thẻ này tuy không hiển thị nhưng cực kỳ quan trọng khi bạn muốn website của mình có thứ hạng cao trong kết quả tìm kiếm của Google.

Thẻ meta cuối cùng cho phép các nhà thiết kế điều khiển được khung hiển thị, tính năng này chỉ có ở HTML5. Khung hiển thị là vùng có thể nhìn thấy của người dùng trên một trang web, nó phụ thuộc vào kích thước màn hình các thiết bị khác nhau, ví dụ các thiết bị di động thông minh hiện rất phổ biến nhưng màn hình nó khá nhỏ nên cần trình bày lại sao cho đọc được nội dung dễ dàng.

  Tổng hợp 50+ thẻ HTML phổ biến nhất

4. Thành phần thẻ HTML có ngữ nghĩa

Các thẻ HTML được chia ra thành hai loại:

  • Semantic element là các thẻ có ngữ nghĩa, ví dụ thẻ <form><table><img>
  • Non-semantic element: các thẻ không có ngữ nghĩa, ví dụ <div><span>

Các phiên bản HTML mới sẽ có nhiều hơn các thẻ có ngữ nghĩa vì khi sử dụng các thẻ này có nhiều lợi ích:

  • Dễ dàng chỉnh sửa và duy trì: Với các thẻ không ngữ nghĩa khó phân tách lại phần đánh dấu bằng các thẻ, do đó rất khó để hiểu được bố cục tổng thể và ý nghĩa các thành phần.
  • Tăng khả năng truy xuất: các trang web hiện đại viết bằng HTML5 có khả năng điều hướng thông qua các liên kết, menu tốt hơn chỉ bằng các công cụ cơ bản do nó đưa ra thành phần HTML mới là <nav> thay cho việc dùng các thẻ <div>.
  • Tốt hơn cho bộ máy tìm kiếm: đây là một trong những lợi ích lớn nhất, bạn muốn trang web của mình được nhiều người biết đến thông qua các kết quả tìm kiếm, việc sử dụng các thẻ có ngữ nghĩa giúp Google nhanh chóng phân tích được nội dung một cách chính xác và tối ưu hóa cho bộ máy tìm kiếm.
  • Thích hợp cho các trình duyệt tương lai: các trình duyệt mới và công cụ thiết kế web mới sẽ tận dụng các thông tin về ngữ nghĩa.

4.1 Sự tiến hóa trong HTML5

Trong HTML5 xuất hiện nhiều hơn các thẻ HTML có ngữ nghĩa, ví dụ như <header><footer><nav><article>… tại sao vậy, sự tiến hóa của HTML là tất yếu khách quan khi mà nhu cầu tạo ra các thành phần cơ bản của một trang HTML ngày càng lớn. Quay ngược lại hơn 10 năm trước, những khảo sát về HTML giúp ta có được câu trả lời.

Năm 2004, một thành viên nhóm soạn thảo đặc tả HTML5, Ian Hickson đã làm một thống kê trên một tỉ trang web thông qua hệ thống chỉ mục của Google để tìm xem thực tế cách tạo ra các trang web. 5 năm sau đó, Opera MAMA cũng thực hiện một việc tương tự nhưng với các thuộc tính class của thẻ HTML từ ngẫu nhiên hơn 2 triệu đường dẫn và kết quả như sau:

STT Giá trị thuộc tính class Tần suất lặp lại
1 footer 179,528
2 menu 146,673
3 style1 138,308
4 msonormal 123,374
5 text 122,911
6 content 113,951
7 title 91,957
8 style2 89,851
9 header 89,274
10 copyright 86,979
11 button 81,503
12 main 69,620
13 style3 69,349
14 small 68,995
15 nav 68,634
16 clear 68,571
17 search 59,802
18 style4 56,032
19 logo 48,831
20 body 48,052

Bảng kết quả tiếp theo khi thống kê thuộc tính id của thẻ HTML từ 1.5 triệu đường dẫn ngẫu nhiên:

STT Giá trị thuộc tính id Tần suất lặp lại
1 footer 288,061
2 content 228,661
3 header 223,726
4 logo 121,352
5 container 119,877
6 main 106,327
7 table1 101,677
8 menu 96,161
9 layer1 93,920
10 autonumber1 77,350
11 search 74,887
12 nav 72,057
13 wrapper 66,730
14 top 66,615
15 table2 57,934
16 layer2 56,823
17 sidebar 52,416
18 image1 48,922
19 banner 44,592
20 navigation 43,664

Từ các thống kê này, trong HTML5 người ta thấy rằng cần thiết phải đưa vào thêm một số các thẻ HTML có ngữ nghĩa mới như nav, header, footer… Những thẻ HTML có ngữ nghĩa mới này đã làm thay đổi cấu trúc trang HTML cơ bản. Nếu các bạn có điều kiện thực hiện các trang web từ những năm đầu của thế kỷ 21 có thể thấy cách cấu trúc đã có những đợt thay đổi như sau:

  • 2000-2005: Sử dụng thẻ table để cấu trúc trang HTML
  • 2005-2010: Sử dụng thẻ div để cấu trúc trang HTML
  • 2010 đến nay: Sử dụng các thẻ HTML có ngữ nghĩa mới trong HTML5 để cấu trúc trang.

Các ví dụ tiếp theo đây cho thấy được những thay đổi đáng kể trong cách cấu trúc trang HTML, đầu tiên chúng ta xem xét cách cấu trúc dùng thẻ div

Cấu trúc trang HTML sử dụng thẻ div

<div id="header">
  <h1>Khóa học HTML5 cơ bản</h1>
</div>
<div id="sidebar">
  <h2>Menu</h2>
  <ul>
    <li><a href="html5-introduction.html">Chương I: Giới thiệu HTML5</a></li>
    <li><a href="html5-contruction.html">Chương II: Cấu trúc trang HTML</a></li>
    <li><a href="html5-form.html">Chương III: Xây dựng form nhập liệu</a></li>
  </ul>
</div>
<div class="post">
  <h2>HTML5 là gì?</h2>
  <p>Ngôn ngữ HTML5 giúp tạo ra các trang web một cách nhanh chóng đáp ứng được các nhu cầu thực tế.</p>
</div>
<div class="post">
  <h2>Cấu trúc trang HTML cơ bản</h2>
  <p>HTML5 đã có những cải tiến thay đổi cách cấu trúc trang HTML bằng semantic element.</p>
</div>
<div id="footer">
  <p><small> Bản quyền thuộc về Allaravel.com. 2018</small></p>
</div>

Với việc thêm vào các thẻ HTML có ngữ nghĩa mới trong HTML5, cấu trúc trang HTML đã thay đổi đáng kể:

Cấu trúc trang HTML sử dụng thẻ HTML có ngữ nghĩa

Mã HTML cũng có những thay đổi

<header>
  <h1>Khóa học HTML5 cơ bản</h1>
</header>
<nav>
  <h2>Menu</h2>
  <ul>
    <li><a href="html5-introduction.html">Chương I: Giới thiệu HTML5</a></li>
    <li><a href="html5-contruction.html">Chương II: Cấu trúc trang HTML</a></li>
    <li><a href="html5-form.html">Chương III: Xây dựng form nhập liệu</a></li>
  </ul>
</nav>
<article>
  <h2>HTML5 là gì?</h2>
  <p>Ngôn ngữ HTML5 giúp tạo ra các trang web một cách nhanh chóng đáp ứng được các nhu cầu thực tế.</p>
</article>
<article>
  <h2>Cấu trúc trang HTML cơ bản</h2>
  <p>HTML5 đã có những cải tiến thay đổi cách cấu trúc trang HTML bằng semantic element.</p>
</article>
<footer>
  <p><small> Bản quyền thuộc về Allaravel.com. 2018</small></p>
</footer>

4.2 Trình duyệt không tương thích với HTML5

Thật may là các thẻ HTML có ngữ nghĩa trong HTML5 được hỗ trợ diện rộng trên các trình duyệt web hiện đại, rất khó để có thể tìm thấy các phiên bản Chrome, Firefox, Safari hoặc Opera không hỗ trợ. Nhưng không phải là không có những ngoại lệ, ví dụ các phiên bản Internet Explorer trước IE9 là gặp vấn đề với HTML5.

Khi một trình duyệt không phát hiện ra các thẻ HTML mới, nó sẽ xử lý các thẻ này như một inline element và không hiển thị chúng như các khối (block), để khắc phục vấn đề này, bạn cần thêm một ít code CSS vào:

article, aside, figure, span, footer, header, main, nav, section, summary { 
  display: block; 
}

Code CSS này không ảnh hưởng gì với các trình duyệt có thể nhận diện được thẻ HTML5. Kỹ thuật này là đủ để giải quyết vấn đề tương thích với hầu hết các trình duyệt, tuy nhiên với IE8 hoặc phiên bản thấp hơn thì có một thách thức khác: Các trình duyệt này từ chối áp dụng định dạng CSS cho các thẻ HTML mà chúng không thể nhận ra. Với vấn đề này chúng ta xử lý bằng cách đưa vào một đoạn mã Javascript giúp IE có thể nhận ra và style các thẻ HTML:

<script>
  document.createElement(‘header’);
  document.createElement(‘nav’);
  document.createElement(‘article’);
  document.createElement(‘footer’);
</script>

Nhóm phát triển Google cũng đưa ra một giải pháp riêng tổng thể hơn với một thư viện Javascript giúp cho mọi trình duyệt không hỗ trợ HTML5 có thể hoạt động được.

<head>
  <!--[if lt IE 9]> 
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> 
  <![endif]-->
</head>

5. Các thẻ HTML mới trong HTML5

5.1 Thẻ HTML5

Thẻ <header> xác định tiêu đề cho một trang hoặc một phần của trang, thẻ được sử dụng như một “khung chứa” cho các nội dung giới thiệu hoặc có thể bao gồm cả các điều hướng trang. Thẻ <header> không bắt buộc phải có trong trang và có thể có nhiều thẻ <header> trong một trang.

Trong hầu hết các trang web, thành phần đầu tiên thường là tiêu đề, nó có thể chứa tiêu đề của website, hình ảnh logo, các liên kết đến trang chủ… Thẻ <header> có thể chứa các thẻ tiêu đề từ h1 đến h6 hoặc một thẻ <hgroup> để nhóm các tiêu đề ở các mức khác nhau nhưng không bắt buộc. Thực tế khi xây dựng website, thành phần <header> có thể được sử dụng để tạo ra bảng nội dung, form tìm kiếm, phần logo trang…

<header>
  <a href="/"><img src=logo.png alt="Trang chủ"></a>
  <h1>Khóa học HTML5 cơ bản</h1>
</header>

Hoặc bạn có thể sử dụng <hgroup> để nhóm các tiêu đề với nhau:

<header>
  <a href="/"><img src=logo.png alt="Trang chủ"></a>
  <hgroup>
    <h1>Khóa học HTML5 cơ bản</h1>
    <h2>15 bài lý thuyết, có bài tập thực hành, câu hỏi trắc nghiệm.</h2>
  </hgroup>
</header>

Đôi khi tiêu đề cũng có thể chứa các thành phần điều hướng đặc biệt khi thiết kế website kiểu master template có một mẫu cho tất cả các trang. Ví dụ:

<header>
  <hgroup>
    <h1>Khóa học HTML5 cơ bản</h1>
    <h2>15 bài lý thuyết, có bài tập thực hành, câu hỏi trắc nghiệm.</h2>
  </hgroup>
  <nav>
    <ul>
      <li><a href="/">Trang chủ</a></li>
      <li><a href="html5-basic.html">HTML5 cơ bản</a></li>
      <li><a href="html5-advance.html">HTML5 nâng cao</a></li>
    </ul>
  </nav>
</header>

Chú ý, thẻ <nav> không bắt buộc phải có trong <header> và hoàn toàn có thể đưa thẻ này ra khỏi thẻ <header>. Nó phụ thuộc vào thiết kế bố cục của website, độ lớn các menu điều hướng. Trong ví dụ tiếp theo, chúng ta không thể đưa thẻ

Template Method Pattern – Khuôn mẫu cho tất cả

Template Method Pattern

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Chào mọi người, hôm nay mình sẽ tiếp tục loạt bài về Design Pattern với một pattern mới: Template Method Pattern. Từ template làm chúng ta liên tưởng đến các template trong thiết kế web, khi chúng ta có 1 trang template đã có sẵn header, footer, navigation, chỉ riêng phần boby là để trống và sẽ display nội dung theo từng page. Nghĩa là chỉ có phần body là sẽ thay đổi theo từng page, còn các phần khác sẽ giống nhau cho tất cả các page. Trừ 1 số page đặc biệt mà nội dung của header, footer, navigation sẽ thay đổi. Việc làm này sẽ giúp giảm thiểu các công việc giống nhau ở nhiều nơi. Thay vì phải viết tất cả các thành phần ở mỗi page, thì bây giờ các thành phần chung sẽ được gom lại và đặt trong một template.

  Factory Pattern - Nhà máy của những đối tượng
  Giải thích Flux Pattern theo phong cách John Wick

Trong lập trình, khái niệm template cũng tương tự như vậy. Nếu các bạn đã từ sử dụng từ khóa abstract trong Java thì khả năng cao là chính các bạn cũng đang sử dụng mẫu template này đấy.

Hãy cụ thể hóa bài toán web template ở trên vào ngôn ngữ lập trình minh họa bằng Java.

Đầu tiên hãy xây dựng một lớp PageTemplate

PageTemplate.java

package behavior.templatemethod;

public abstract class PageTemplate {

protected void displayHeader() {
System.out.println("HEADER");
}

protected void displayNavigation() {
System.out.println("NAVIGATION");
}

protected void displayFooter() {
System.out.println("FOOTER");
}

/**
* Let each subclass define it own content
* @author Edward
*/
protected abstract void displayBody();

/**
* Display all content of web page
* @author Edward
*/
public void displayWebPage() {
displayHeader();
displayNavigation();
displayBody();
displayFooter();
}
}

Lớp PageTemplate đã có sẵn các phương thức để hiển thị các thành phần header, footer, navigation. Riêng phương thức displayBody sẽ là abstract method, các trang khác nhau sẽ có nội dung hiển thị khác nhau. Sau đó cùng hiển thị tất cả lên màn hình theo một thứ tự đã cho trước trong hàm displayWebPage. Bây giờ hãy tạo ra 1 số trang sử dụng template này.

DesignPatternPage.java

package behavior.templatemethod;

public class DesignPatternPage extends PageTemplate {
@Override
protected void displayBody() {
System.out.println("DESIGN PATTERN CONTENT");
}
}

Java8TutorialPage.java

package behavior.templatemethod;

public class Java8TutorialPage extends PageTemplate {
@Override
protected void displayBody() {
System.out.println("JAVA 8 TUTORIAL CONTENT");
}
}

ContactPage.java

package behavior.templatemethod;

public class ContactPage extends PageTemplate {
@Override
protected void displayBody() {
System.out.println("ABOUT CONTENT");
}

@Override
protected void displayNavigation() {
// We do NOT want to display Navigation here
// Just do nothing
}
}

Các lớp trên đều kế thừa từ lớp PageTemplate. Chúng có một yêu cầu bắt buộc là phải implement lại method displayBody để hiển thị nội dung cho từng trang. Riêng có lớp ContactPage sẽ implement lại method displayNavigation để không hiển thị gì. Viết một lớp để test tất cả:

TemplateMethodTest.java

package behavior.templatemethod;

public class TemplateMethodTest {

public static void main(String[] args) {
PageTemplate designPattern = new DesignPatternPage();
designPattern.displayWebPage();

System.out.println();

PageTemplate java8Tutorial = new Java8TutorialPage();
java8Tutorial.displayWebPage();

System.out.println();

PageTemplate contact = new ContactPage();
contact.displayWebPage();
}

}

Kết quả khi output:

HEADER
NAVIGATION
DESIGN PATTERN CONTENT
FOOTER

HEADER
NAVIGATION
JAVA 8 TUTORIAL CONTENT
FOOTER

HEADER
ABOUT CONTENT
FOOTER

Cùng xem qua Class diagram mối quan hệ giữa các class với nhau

TemplateMethod_ClassDiagram

Như ta thấy, tất cả các page sẽ đều có chung các thành phần trong template đã định nghĩa, chúng chỉ cần implement lại những thành phần mà CHỈ CÓ RIÊNG nó mới quyết định được. Vậy nguyên lý của Template Method pattern này là: Đặt tất cả những xử lý chung trong lớp cha, sau đó định nghĩa các hàm abstract và để các lớp con tự định nghĩa lấy. Việc này sẽ giảm thiểu sự trùng lặp code và dễ dàng bảo trì về sau khi mỗi lớp con cần có sự thay đổi.

Các bạn có thể tham khảo thêm các bài viết về Design Pattern trong Series về Design Pattern

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Cách học một công nghệ mới

Cách học một công nghệ mới

Bài viết được sự cho phép của tác giả Tino Phạm

Trong bài này, mình xin chia sẽ cách học của mình khi tiếp cận một công nghệ mới. Bạn có thể tham khảo và chia sẽ lại với mình về cách học của bạn.

  "Khi công nghệ không chỉ dành cho nam giới" - Lea Trúc, Founder của Women Meet Tech

  10 bí kíp để startup và FinTech startup thành công đột phá

Bước 1: đọc và làm theo chính xác những gì người khác hướng dẫn. Làm đúng theo từng bước của họ. Đảm bảo chúng ta phải chạy được giống như những gì họ đã làm.

Bước 2: xem lại code đã viết và đặt câu hỏi tại sao? và nó có nghĩa gì? Từ đó đọc lại hướng dẫn và search google để tìm hiểu để giúp bạn hiểu rõ hơn những gì bạn đã làm.

Bước 3: đập hết mọi thứ và làm lại từ đầu. Lúc này bạn cần thống kê lại mình sẽ làm gì?làm thế nào?. Liệt kê các bước thực hiện. Trong quá trình làm lại bạn sẽ gặp phải lỗi, bạn tìm cách fix nó, từ đó sẽ giúp bạn hiểu rõ hơn vấn đề và giúp bạn có thêm kinh nghiệm với công nghệ mới mà bạn đang học.

Bước 4: Lặp lại bước 1 tới bước 3 với nhiều projects khác nhau hoặc trên cùng một project càng nhiều càng tốt.

Bước 5: Tiến hành hoàn thiện và nâng cập cho những projects mà bạn đã thực tập (Refactor, optimize, improve code,…).

Trên đây là các bước mà mình thường sử dụng khi học một công nghệ mới. Hy vọng được các bạn chia sẽ thêm về cách học của các bạn.

Bài viết gốc được đăng tải tại thangphampt.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Đọc ghi file trên Node.js

Đọc ghi file trên Node.js

Bài viết được sự cho phép của smartjob.vn

Bài này mình giới thiệu về phần đọc ghi file .Trong Node js có nét mới là đọc ghi file khác so với PHP có 2 chế độ là : Đồng bộ và không đồng bộ ( hay có khái niệm mới Synchronous vs Asynchronous).Asynchronous :bất đồng bộ khi tiến trình bắt đầu chạy thì tất cả cách lệnh cùng chạy và Synchronous :đồng bộ khi tiến trình chạy thì các câu lệnh được đọc  trình tự từ trên xuống dưới.

  10 Công ty hàng đầu thế giới sử dụng Node.js
  Ghi chú file package.json của node module

Bắt đầu ví dụ : tạo 2 file : file.js và sample.txt trong thư mục  E:\file_nodejs như sau :

1. Asynchronous

đọc ghi file bất đồng bộ tiến trình bắt đầu tất cả các dòng lệnh cùng chạy 

Nội dung trong file : file.js

Nội dung trong file : example.txt

Sau đó cmd mở của sổ lênh command line trỏ tới thư mục chứa file file.js và gõ lệnh:

Màn hình sẽ hiển thị lên:

Ghi file bất  đồng bộ cũng tương tự  tạo file writefile.js có nội dung như sau :

Sau đó cmd mở của sổ lênh command line trỏ tới thư mục chứa file writefile.js và gõ lệnh:

Mở file sample.txt  sẽ có nội dung như sau :

2. Synchronous đọc ghi file đồng bộ (tuần tự từ trên xuống)

Cũng làm tương tự với đọc file  nhưng code 2 file file.js và writefile.js như sau

file writefile.js nội dung:

Trên là hướng dẫn trên môi trường window với các cài riêng gói node.js

skype: nguyenanhdung90

Bài viết gốc được đăng tải tại smartjob.vn

Xem thêm Việc làm nodeJS hấp dẫn trên TopDev

Tìm việc làm IT Đà Nẵng, Hồ Chí Minh, Hà Nội mới nhất

Facade Pattern – Đơn giản hóa tất cả

facade pattern

Bài viết được sự cho phép của tác giả Edward Thien Hoang

FACADE PATTERN

Chào mọi người, hôm nay mình sẽ tiếp tục loạt bài về Design Pattern với một pattern mới: Facade Pattern. Cái tên nghe rất lạ nhưng khi bước vào implement, các bạn sẽ thấy đây là mẫu pattern gần gũi và được sử dụng nhiều nhất trong chương trình.

  Các loại Design patterns
  Design pattern là gì? Tại sao nên sử dụng Design pattern?

ĐỊNH NGHĨA

Nói một cách đơn giản như chính việc implement pattern này, giúp Client đơn giản hóa các lời gọi hàm từ nhiều object khác nhau bằng cách cung cấp 1 interface đơn giản hơn để Client làm việc. Điều này giúp đơn giản hóa và giảm độ phụ thuộc của Client đến các object bên trong.

Hình phía dưới sẽ minh họa cho điều mình vừa nói ở trên:

facade

Các Client thay vì phải gọi vào nhiều component phía trong, đối tượng Facade sẽ đảm nhiệm việc đó và cung cấp các interface đơn giản hơn đến Client.

VÍ DỤ

Hãy lấy một ví dụ có sẵn trong Java Swing, lớp javax.swing.JOptionPane:

facade_advanced2

JOptionPane được thiết kế như một đối tượng Facade. Thay vì phải gọi trực tiếp đến các lớp phía trong như: JDialog, BorderFactory, Panel… để tạo ra các dialog như: Confirm, Input, Message and OptionDialogs. Thì bây giờ chỉ cần thông qua JOptionPane, nó sẽ giúp chúng ta làm chuyện đó.

Dưới đây là 1 ví dụ nếu không sử dụng JOptionPane

...
JFrame frame = new JFrame("My Message Dialog");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Quit");
JLabel label = new JLabel("This is My Message Dialog!");

ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
System.exit(0);
}
};

button.addActionListener(actionListener);
Container contentPane = frame.getContentPane();
contentPane.add(label, BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);
frame.setSize(300, 200);
frame.setVisible(true);
...

Quá phức tạp và quá nhiều phụ thuộc. Nếu sử dụng JOptionPane như là 1 Facade thì mọi chuyện sẽ chỉ đơn giản như dưới đây:

...
JOptionPane optionPane = new JOptionPane(
"This Dialog is generated by the JOptionPane Facade!",
JOptionPane.OK_OPTION);
// OR
JDialog dialog = optionPane.createDialog(frame.getContentPane(),
"JOptionPane Message Dialog");
dialog.setVisible(true);
...

Kết thúc bài viết về Facade Pattern tại đây. Các bạn chỉ cần nhớ 1 điều, khi có nhiều lời gọi qua nhiều lớp đối tượng hãy nghĩ đến Facade để đơn giản hóa chúng, mọi thay đổi trong các lời gọi hàm sẽ được thực hiện trong lớp Facade mà không ảnh hưởng đến chương trình.

Có một mẫu design cũng gói lại nhiều lớp đối tượng để đưa ra những xử lý đơn giản hơn đó là Mediator Pattern. Trong khi Facade Pattern hướng đến việc cung cấp những API đơn giản hơn từ đến Client, thì Mediator sẽ dùng cho mục đích khác, tách biệt nhiều xử lý phức tạp trong các lớp đối tượng, và có thể thêm hoặc bớt bất cứ thành phần nào trong đó. Cùng đọc về Mediator Pattern để đưa ra sự so sánh chính xác nhất với 2 Pattern này.

Các bạn có thể tham khảo thêm các bài viết về Design Pattern trong Series về Design Pattern

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Ngắm và bắn với thuộc tính watch trong Vue instance

Ngắm và bắn với thuộc tính watch trong Vue instance

Bài viết được sự cho phép của tác giả Kien Dang Chung

Trong lập trình chúng ta thấy các ứng dụng là sự tác động qua lại giữa dữ liệu và các phương thức xử lý dữ liệu, với góc nhìn này chúng ta thấy được lý do tại sao có các thành phần trong Vue instance như data, methods, computed. Từ đây một câu hỏi được đặt ra, còn thành phần nào liên quan đến dữ liệu và phương thức xử lý dữ liệu? Để trả lời câu hỏi này, bạn hãy cùng tôi rà soát các vấn đề cần làm xung quanh dữ liệu:

  10 kinh nghiệm khi làm việc với các dự án lớn viết bằng Vue.js
  3 phút làm quen với Vue.js

Vue instance

  • Dữ liệu và tự bản thân nó thể hiện trong phần data, trong hệ thống reactivity.
  • Tính toán, thao tác với dữ liệu đã có các computed property.
  • Với mỗi dữ liệu, thực hiện các phương thức riêng đã có methods.
  • Sự thay đổi của dữ liệu dẫn đến các thao tác đặc biệt thì xử lý thế nào?

Vấn đề cuối cùng có thể xử lý bằng computed property nhưng đây là các thuộc tính nên nó không có tham số đầu vào, chính vì vậy có một khái niệm nữa là watcher là những “đơn vị giám sát” dữ liệu trong thành phần data của Vue instance và thực hiện những công việc cần thiết để bổ sung công cụ cho chúng ta khi viết ứng dụng.

1. Watcher là gì trong framework Vue.js?

Đúng như tên gọi của nó, watcher giám sát các thay đổi trong một đối tượng, sử dụng watcher có thể có cùng kết quả với các giá trị được tính toán trước trong computed property nhưng với watcher nó phức tạp hơn. Chúng ta thường sử dụng watcher với những tình huống đòi hỏi phải xử lý phức tạp như:

  • Các hoạt động bất đồng bộ đáp ứng lại việc thay đổi dữ liệu
  • Các thiết lập giá trị ngay lập tức
  • Hạn chế số lần thực hiện phương thức khi dữ liệu thay đổi.

Watcher có thể được khai báo trong thành phần watch của Vue instance, cú pháp như sau:

  new Vue({
    el: '#app',
    data: {
      // Dữ liệu gán với view
    },
    watch: {
      // Các hoạt động bất đồng bộ muốn thực hiện khi dữ liệu thay đổi
    }
  });

Trong ví dụ tiếp theo, chúng ta xây dựng một ứng dụng giả lập công cụ tìm kiếm trực tuyến mà mỗi khi gõ vào một chuỗi truy vấn tìm kiếm ngay lập tức có câu trả lời. Hoạt động của ứng dụng này như sau, ứng dụng liên tục kiểm tra xem có sự thay đổi trong ô nhập truy vấn tìm kiếm hay không, nếu có nó sẽ gửi từ khóa đến một API để lấy câu trả lời. Chúng ta sẽ khai báo một phương thức giám sát (watcher) ô tìm kiếm.

<!DOCTYPE html>
<html>
<head>
    <title>Watcher Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container" id="app">
        <input class="form-control" type="text" @input="isTyping = true" v-model="searchQuery">
        <p v-if="isTyping">Đang tìm kiếm...</p>
        <div v-else>
            <ul class="list-group">
                <li class="list-group-item" v-for="result in results">{{ result }}</li>
            </ul>
        </div>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                searchQuery: '',
                results: [],
                isTyping: false
            },
            watch: {
                searchQuery: function(query) {
                    console.log(query);
                    var vm = this;
                    setTimeout(function() {
                        console.log('setTimeout call');
                        vm.results = ['Vue.js', 'React', 'Angular 2'];
                        vm.isTyping = false;
                    }, 1000);
                } 
            }
        });
    </script>
</body>
</html>

Đoạn mã trên là rất dễ hiểu với một View có một ô nhập liệu được gán dữ liệu hai chiều với một Model là searchQuery thông qua v-model (Xem lại Gán dữ liệu hai chiều với v-model nếu bạn chưa biết về v-model). Trên ô nhập liệu này chúng ta cũng kiểm tra sự kiện nhập liệu để có thông báo lên “Đang tìm kiếm…” thông qua v-on:input và viết tắt thành @input (Xem thêm Quản lý sự kiện với v-on).

    <div class="container" id="app">
        <input class="form-control" type="text" @input="isTyping = true" v-model="searchQuery">
        <p v-if="isTyping">Đang tìm kiếm...</p>
        <div v-else>
            <ul class="list-group">
                <li class="list-group-item" v-for="result in results">{{ result }}</li>
            </ul>
        </div>
    </div>

Kết quả tìm kiếm được hiển thị trong một danh sách được đưa vào thẻ <ul> với directive v-for duyệt qua các kết quả và hiển thị từng kết quả trong thành phần danh sách <li>.

Tiếp đến là phần quan trọng nhất trong đoạn code này, giám sát sự thay đổi của searchQuery và truyền chuỗi truy vấn người dùng nhập vào đến API xử lý.

watch: {
    searchQuery: function(query) {
        var vm = this;
        setTimeout(function() {
            vm.results = ['Vue.js', 'React', 'Angular 2'];
            vm.isSearching = false;
        }, 1000);
    }
}

Ở đây chúng ta đưa vào hàm setTimeout với thời gian chờ là 1 giây để giả lập thời gian xử lý truy vấn từ API, sau 1 giây kết quả trả về là một mảng tên các framework Javascript. Khi sử dụng hàm setTimeout có một chú ý là biến this sẽ trỏ đến đối tượng window chứ không phải trỏ đến Vue instance như chúng ta mong muốn. Như vậy chúng ta cần sao chép Vue instance sang một biến khác để tham chiếu bên trong hàm setTimeout().

Chương trình chạy ok nhưng có một vấn đề xảy ra, có quá nhiều lời gọi đến setTimeout không cần thiết khi mà người dùng gõ quá nhanh. Chúng ta cùng tìm hiểu vấn đề này:

Watcher Vuejs

Có quá nhiều lời gọi setTimeout trong một khoảng thời gian quá ngắn khi mà người dùng đang gõ chuỗi truy vấn, làm thế nào để khắc phục vấn đề này? Đây là một vấn đề rất hay gặp phải khi xử lý các đoạn mã bất đồng bộ. Chúng ta sử dụng đến hàm _.debound() là một hàm trong bộ thư viện lodash, nó cho phép ngừng một thời gian và chỉ gọi phương thức xử lý một lần sau khoảng thời gian đó. Code khi sử dụng lodash như sau:

<!DOCTYPE html>
<html>
<head>
    <title>Watcher Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container" id="app">
        <input class="form-control" type="text" @input="isSearching = true" v-model="searchQuery">
        <p v-if="isSearching">Searching...</p>
        <div v-else>
            <ul class="list-group">
                <li class="list-group-item" v-for="result in results">{{ result }}</li>
            </ul>
        </div>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                searchQuery: '',
                results: [],
                isSearching: false
            },
            watch: {
                searchQuery: _.debounce(function (query) {
                    console.log(query);
                    this.results = ['Vue.js', 'React', 'Angular 2'];
                    this.isSearching = false;
                }, 1000) 
            }
        });
    </script>
</body>
</html>

Watcher Vuejs sử dụng hàm debound trong lodash

Bạn thấy đấy, watcher này vẫn giám sát sự thay đổi của searchQuery nhưng chỉ thực sự xử lý khi phương thức này tạm dừng một giây, tức là khi nào người dùng ngừng gõ 1 giây thì mới gửi chuỗi truy vấn đến API để xử lý. Với cách xử lý này, nó giúp cho hạn chế số lượng lời gọi đến API mà vẫn cho kết quả cuối cùng, các lời gọi khác do xử lý quá nhanh nên chưa kịp cho ra kết quả đã phải xử lý tiếp theo gây dư thừa xử lý trên phía máy chủ cung cấp API.

2. Tham số đầu vào của watcher

Trong ví dụ trên chúng ta thấy watcher cho searchQuery có tham số đầu vào là query chính là chuỗi truy vấn người dùng nhập vào, đây là giá trị mới nhất của searchQuery. Chúng ta cũng có thể lấy lại giá trị trước đó của searchQuery thông qua tham số thứ hai của watcher.

watch: {
    searchQuery: function(newVal, oldVal) {
        console.log(newVal);
        console.log(oldVal);
    }
}

Tham số đầu tiên của watcher là newVal sẽ chứa giá trị mới nhất của thuộc tính đang được “giám sát”, tham số thứ hai oldVal chứa giá trị trước khi có thay đổi của thuộc tính được giám sát. Watcher cũng có thể chỉ có một tham số đầu vào.

watch: {
    searchQuery: function(newVal) {
        console.log(newVal);
    }
}

3. Giám sát thuộc tính được lồng bên trong đối tượng

Đối tượng trong thành phần data của Vue instance có thể rất phức tạp với các thuộc tính được lồng ở cấp sâu hơn, ví dụ:

data: {
    person: {
        name: 'Nguyễn Văn A',
        drivingLicense: {
            id: 'GPLX0393928282',
            issueDate: '20180417',
            issueBy: 'Bộ GTVT'
        }
    }
}

Khi đó nếu chúng ta muốn giám sát thuộc tính issueDate thì sử dụng cú pháp tham chiếu đến thuộc tính thông qua dấu chấm.

watch: {
    'person.drivingLicense.issueDate': function(newVal, oldVal) {
        alert('Giấy phép được gia hạn từ ' + oldVal + ' sang ' + newVal);
    }
}

Nếu bạn không muốn sử dụng cách tham chiếu với dấu chấm và dấu nháy đơn có thể gói nó vào trong một computed property:

computed: {
    licenseIsUpgrade() {
        return this.person.drivingLicense.issueDate;
    }
},
watch: {
    licenseIsUpgrade: function(newVal, oldVal) {
        alert('Giấy phép được gia hạn từ ' + oldVal + ' sang ' + newVal);
    }
}

Trên đây chúng ta mới chỉ giám sát sự thay đổi của các thuộc tính trong một đối tượng, nếu giám sát cả đối tượng thì thế nào? Trong watcher có thể khai báo mức độ giám sát thông qua thuộc tính deep.

watch: {
    'person': {
        handler: function (newVal, oldVal) {
            console.log('Giám sát đối tượng', ' giá trị cũ: ', newVal, ' giá trị cũ:', oldVal)
        },
        deep: true
    }
}

Khi đó bất kể thành phần nào của đối tượng person thay đổi thì watcher đều nhìn thấy. Chú ý, với ví dụ này newVal và oldVal sẽ cùng giá trị bởi vì khi thay đổi đối tượng hoặc mảng, Vue không giữ bản sao của giá trị trước đó. Cả hai tham số sẽ cùng tham chiếu đến cùng một đối tượng hoặc mảng, bởi vậy khi viết code liên quan đến giá trị cũ và mới của đối tượng hoặc mảng chúng ta phải có thêm phần xử lý.

data: {
    person: {
        name: 'Nguyễn Văn A',
        drivingLicense: {
            id: 'GPLX0393928282',
            issueDate: '20180417',
            issueBy: 'Bộ GTVT'
        }
    }
}
computed: {
    clonePerson: function() {
        return JSON.parse(JSON.stringify(this.person));
    }
},
watch: {
    clonePerson: function(newVal, oldVal) {
        alert(JSON.stringify(newVal));
        alert(JSON.stringify(oldVal));
    }
}

4. Thêm hoặc hủy bỏ các watcher trong khi chạy ứng dụng

Khi khai báo các watcher chúng ta khai báo trong Vue Instance, vậy nếu chúng ta muốn thêm các watcher hoặc hủy bỏ chúng đi ở bên ngoài thực thể Vue thì sao? Bạn hoàn toàn yên tâm, Vue instance có biến $watch giúp bạn thực hiện công việc này.

<!DOCTYPE html>
<html>
<head>
    <title>Watcher Vue.js - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container" id="app">
        <p>Counter: {{ counter }}</p>
        <button @click="counter++">Tăng bộ đếm</button>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.min.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                counter: 1
            }
        });
        vm.$watch('counter', function(newValue, oldValue) {
            alert('Bộ đếm tăng từ ' + oldValue + ' lên ' + newValue + '!');
        });
    </script>
</body>
</html>

Với watcher được thêm vào ở ngoài Vue instance cũng có tham số để thiết lập xem chúng ta giám sát cả đối tượng hay không?

vm.$watch('person', function(newVal, oldVal) {
    alert('Nhân sự thay đổi từ ' + oldVal.fullName + ' sang ' + newVal.fullName + '!');
}, { deep: true });

Với các watcher phức tạp, có thể thay biểu thức tham chiếu đến một thuộc tính đối tượng thông qua toán tử dấu chấm bằng một hàm trả về biểu thức cần giám sát.

vm.$watch(
    function() {
        return this.counter;
    },
    function(newValue, oldValue) {
        alert('Bộ đếm tăng từ ' + oldValue + ' lên ' + newValue + '!');
    }
);

Chúng ta đã nói đến việc thêm watcher ở ngoài Vue instance, vậy làm cách nào để Vue không giám sát tiếp các thuộc tính trong data? Rất đơn giản, phương thức $watch() trả về một phương thức mà nếu chúng ta gọi đến phương thức này, Vue sẽ không giám sát thuộc tính trong data nữa.

var vm = new Vue({
    el: '#app',
    data: {
        counter: 1
    }
});
var unwatch = vm.$watch(
    function() {
        return this.counter;
    },
    function(newValue, oldValue) {
        alert('Bộ đếm tăng từ ' + oldValue + ' lên ' + newValue + '!');
    }
);
// Sau 10 giây ngừng giám sát thuộc tính counter của data
setTimeout(function() {
    unwatch();
}, 10000);

Sau 10 giây mọi thay đổi của counter sẽ không được giám sát nữa.

5. So sánh computed, watch và methods trong Vue instance

Chúng ta cùng xem xét một ví dụ sau:

var vm = new Vue({
    el: '#welcome',
    data: {
        message: 'Hello',
        name: 'World',
        nameEdits: 0
    },
    computed: {
        welcomeMessage: function () {
            return this.message + ' ' + this.name
        }
    },
    watch: {
        name: function () {
            if (this.message.toLowerCase() === 'reset') {
                this.nameEdits = 0
            } else {
                this.nameEdits += 1 
            }
        }
    },
    methods: {
        numRenders: function () {
            console.log('Page rendered')
        }
    }
})

Đầu tiên chúng ta xem phần computed, welcomeMessage chỉ được gọi khi message hoặc name thay đổi vì nó phụ thuộc vào thuộc tính này. Vì vậy, nếu nameEdits thay đổi, welcomeMessage cũng không được gọi. Thuộc tính Computed giúp ứng dụng hoạt động hiệu quả tối ưu mà vẫn có những phản ứng.

Tiếp theo chúng ta sang phần watch, nó đang giám sát thuộc tính name, có nghĩa là bất cứ khi nào name thay đổi, hàm khai báo sẽ được gọi để cập nhật nameEdits. Chú ý, mỗi watch chỉ giám sát trên một thuộc tính, ở đây là name, do đó khi nameEdits và message thay đổi, hàm này không được kích hoạt.

Cuối cùng, chúng ta xem phần methods, numRender được gọi mỗi khi render xong (cụ thể hơn là được gọi khi các đoạn mã gọi đến hoặc sự kiện người dùng khi giao diện đã được render), vì vậy bất cứ khi nào có gì đó được cập nhật trên giao diện người dùng, numberRenders được gọi. Ví dụ, nếu bạn có một ứng dụng hiển thị đồng hồ và nó cập nhật theo từng giây, tất cả các phương thức sẽ được gọi từng giây bất kể phương thức đó làm gì.

6. Bài tập

Continue

7. Lời kết

Các khái niệm trên đây là rất cơ bản khi làm việc với Vue.js do đó bạn cần nắm rõ nó, có thể bạn chỉ mới hiểu lờ mờ nhưng đừng lo các dự án cụ thể sẽ giúp bạn nắm rõ hơn.

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Hàm explode() trong PHP

Hàm explode() trong PHP

Bài viết được sự cho phép của tác giả Kien Dang Chung

Từ phiên bản PHP 4, có một số các hàm xử lý chuỗi rất tiện lợi như explode, implode… giúp cho công việc phân tích, sàng lọc chuỗi dễ chịu hơn nhiều. Trong bài viết này chúng ta sẽ làm quen với hàm explode trong PHP cùng với một số ví dụ hay dùng trong thực tế.

1. Cơ bản về hàm explode trong PHP

Hàm explode trong PHP cho phép bạn chuyển một chuỗi sang một mảng dựa trên các ký tự phân cách. Trong thực tế, xử lý chuỗi là rất cần thiết và sử dụng khá thường xuyên, ví dụ khi bạn muốn tách họ và tên của một người dùng, tách từng từ khóa trong một danh sách từ khóa có phân cách bằng một ký tự nào đó… Cú pháp của hàm explode:

explode(separator,string,limit)

Trong đó:

  • separator: ký tự hoặc chuỗi ký tự phân cách sử dụng để phân biệt các phần tử trong chuỗi.
  • string: chuỗi cần tách thành mảng.
  • limit: xác định số phần tử của mảng đầu ra.
    • >0: trả về mảng có số phần tử là limit phần tử đầu
    • <0: trả về mảng có số phần tử là limit phần tử cuối
    • 0: trả về mảng với 1 phần tử

Chú ý: Hàm explode được giới thiệu từ phiên bản PHP 4, tham số limit được thêm vào từ PHP 4.1 và hỗ trợ giá trị âm từ PHP 5.1.0.

Tìm việc làm PHP đãi ngộ tốt trên TopDev

2. Các ví dụ thực tế sử dụng hàm explode

2.1 Ví dụ đơn giản về explode

Một cách đơn giản để lưu nhiều giá trị vào một cột đó là sử dụng dấu phân cách, cách thức này được sử dụng khá nhiều trước đây khi chưa có các công nghệ như XML, JSON… Ví dụ trong một bảng dữ liệu để lưu thông tin người dùng trong một cột người ta sử dụng chuỗi !# để phân cách các thông tin: Nguyễn Văn A!#19810101!#Hà Nội!#anv@allaravel.com

Để bóc tách chuỗi này chúng ta sử dụng explode

<?php
$strUserInformation = "Nguyễn Văn A!#19810101!#Hà Nội!#anv@allaravel.com";
$arrUserInformation = explode("!#", $strUserInformation);
print_r($arrUserInformation);

Kết quả: Array ( [0] => Nguyễn Văn A [1] => 19810101 [2] => Hà Nội [3] => anv@allaravel.com )

2.2 Ví dụ phân tách từ khóa trong một danh sách từ khóa sử dụng explode

Trong các ứng dụng blog, CMS… trong các bài viết chúng ta thường nhập vào một danh sách từ khóa được phân cách với nhau bằng dấu , hoặc ; hoặc |… vậy làm thế nào để phân cách chuỗi từ khóa này thành một mảng tiện cho xử lý và lưu trữ vào CSDL?

Ví dụ khi danh sách từ khóa, thẻ cho bài viết này như sau: “xử lý chuỗi trong PHP, explode trong PHP; PHP tách chuỗi | PHP string process”, ở đây dấu phân cách sử dụng rất đa dạng.

<?php
$keywords =  "xử lý chuỗi trong PHP, explode trong PHP; PHP tách chuỗi | PHP string process";
$delimiters = array(",",";","|");
$keywords = str_replace($delimiters, $delimiters[0], $keywords);
$arrKeyword= explode($delimiters[0], $keywords);
foreach ($arrKeywordas $key)
{
   // Code xử lý cho từng từ khóa và lưu CSDL
}

Đầu tiên chúng ta thực hiện replace toàn bộ dấu phân cách về một loại, ở đây đưa hết về dấu phẩy. Tiếp theo, sử dụng explode như thông thường để thực hiện chuyển chuỗi thành mảng.

  10 Frameworks tốt nhất hiện nay cho PHP
  10 PHP Instagram Scripts & Widgets tốt nhất

2.3 Lọc họ tên người dùng sử dụng php explode

Trong các ứng dụng để tránh cho người dùng phải mất quá nhiều thao tác khi nhập họ tên thường chúng ta đưa cả họ và tên đầy đủ vào một ô nhập liệu sau đó trong xử lý nghiệp vụ mới bóc tách họ, tên người dùng này. Ví dụ: “Nguyễn Văn A”, để bóc tách họ tên trong PHP chúng ta có thể sử dụng hàm explode:

<?php
$fullName = "Nguyễn Văn A";
$arrName = explode(" ", $fullName);
$firstName = array_shift($arrName); //Họ chính là phần tử đầu tiên của mảng
$lastName = array_pop($arrName); //Tên chính là phần tử cuối cùng của mảng
$middleName = implode(" ", $arrName); //Tên đệm chính là kết nối các phần tử còn lại

Trong ví dụ trên có sử dụng hàm implode, trong PHP hàm này ngược lại với hàm explode. Hàm implode biến một mảng thành một chuỗi.

3. Kết luận

Qua bài viết bạn đã nắm được cách áp dụng explode một cách thành thục khi lập trình PHP. Sử dụng explode giúp giảm thời gian viết code, các xử lý chuỗi cũng đơn giản hơn khi kết hợp với các vòng lặp trong PHP. Nếu bạn có trường hợp nào cần xử lý chuỗi hãy để lại bình luận cuối bài viết nhé, chúng ta sẽ cùng thảo luận.

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev

Truy vấn cơ sở dữ liệu MongoDB bằng PHP

Truy vấn cơ sở dữ liệu MongoDB bằng PHP

Bài viết được sự cho phép của smartjob.vn

MongoDB hỗ trợ rất nhiều Driver cho các ngôn ngữ lập trình khác nhau. Trong bài viết này, SmartJob trình bày về việc kết nối, truy vấn từ PHP.

Máy tính sử dụng: Windows 10, 64 bit, sử dụng bộ tích hợp XAMPP.
Cài đặt MongoDB sử dụng MEAN stack (bạn xem các bài viết trước đã hướng dẫn cách cài đặt).

Xem thêm việc làm mongoBD tại các công ty hàng đầu trên TopDev

Bước 1. Tải về tập tin mở rộng dll tại đường link:

Bước 2. Giải nén. Copy file php_mongodb.dll  vào thư mục ext, ví dụ trên máy của tác giả là: C:\xampp\php\ext

Bước 3. Tìm file php.ini , ví dụ, trên máy tác giả là: C:\xampp\php\php.ini .

Chèn vào cuối tập tin này:

extension=php_mongodb.dll

Bước 4. Giả sử có thư mục: C:\xampp\htdocs\vy\mongophp
Sử dụng cmd:

Gõ lệnh:

composer require "mongodb/mongodb=^1.0.0"

để tải thư viện bằng Composer về.

Composer tự động tải về và thư mục có thêm 1 thư mục và 2 tập tin mới:

Tạo 3 tập tin info.phpadd.phpfind.php để kiểm tra các tính năng mà thư viện MongoDB PHP cung cấp:

Tập tin info.php

Tập tin add.php

Tập tin find.php

Bước 5. Khởi chạy máy chủ PHP dựng sẵn

php -S localhost:1111 -t C:\xampp\htdocs\vy\mongo-php

Bước 6. Truy cập

http://localhost:1111/info.php

xem kết quả để thấy rằng extension MongoDB đã được cài đặt thành công trong PHP.

Bước 7. Thêm dữ liệu bằng cách truy cập đường dẫn

Bước 8. Tìm kiếm dữ liệu, bằng cách truy cập đường dẫn

Để thực hiện nhiều thao tác đa dạng khác (đọc, ghi, sửa, xóa), bạn hãy xem thêm tài liệu như bên dưới.

TÀI LIỆU THAM KHẢO

1. http://php.net/manual/en/mongodb.installation.windows.php
2. http://mongodb.github.io/mongo-php-library/api/class-MongoDB.Collection.html
3. https://gist.github.com/gatesvp/977676

Tải mã nguồn từ server SmartJob: mongo-php
hoặc tải về/fork từ server Github: https://github.com/SmartJobVN/mongo-php

Bài viết gốc được đăng tải tại smartjob.vn

Có thể bạn quan tâm:

Xem ngay những tin đăng tuyển dụng IT mới nhất trên TopDev