Home Blog Page 92

Không phải Source Code, Database mới là quan trọng nhất trong hệ thống?

Không phải Source Code, Database mới là quan trọng nhất trong hệ thống?

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

Chào các bạn, với nhiều anh em lập trình viên có lẽ code là một cái gì đó cao siêu và thể hiện được trình độ của lập trình viên.

Nhưng liệu những dòng code có phải là quan trọng nhất trong một hệ thống hay không? bạn đã từng đặt ra những câu hỏi kiểu như vậy chưa?

Vậy thì để mình trả lời luôn: Tất nhiên là không rồi ! Ngày nay, một hệ thống hay nói đơn giản là một ứng dụng hoặc một phần mềm không chỉ có code và giao diện.

Mà quan trọng hơn rất nhiều đó là cơ sở dữ liệu (database) của hệ thống đó. Vậy câu hỏi đặt ra là tại sao cơ sở dữ liệu lại quan trọng như vậy?

Vâng, thì trong bài viết này mình sẽ cùng anh em chỉ ra 5 lý do thuyết phục để trả lời cho câu hỏi tại sao bên trên nhé.

Tuyển Database lương cao hấp dẫn

#1. Không có database thì rất khó để kiểm thử

Ứng dụng hay phần mềm nào mà chẳng có lỗi và bugs, gần như đó là một tất yếu trong quá trình xây dựng và phát triển phần mềm.

khong-phai-source-code-database-moi-quan-trong-nhat-trong-he-thong (1)

Chính vì vậy, chúng ta phải có khâu kiểm thử phần mềm để hạn chế tối đa các lỗi phát sinh và nâng cao chất lượng phần mềm.

Nhưng sự thật là việc kiểm thử đôi khi lại rất phụ thuộc vào dữ liệu (có thể là dữ liệu test hoặc dữ liệu thật)..

Điều này nghĩa là sao? Mình lấy ví dụ về các ứng dụng quản lý là các ứng dụng có mức độ tương tác với database tương đối cao.

Khi tester thực hiện các thao tác trên giao diện họ phải vào database để kiểm tra xem dữ liệu có được cập nhật hay thêm đúng hay không.

Thậm chí trong nhiều trường hợp (case) họ phải có được data chính xác mới kiểm tra được chức năng chạy đúng hay không.

Nói chung là bộ phận kiểm thử (tester) là những người phải nắm được cấu trúc của database, biết cách lọc, truy xuất dữ liệu từ database.

#2. Giảm mức độ tính toán cho bộ phận khác trong hệ thống

Mình lấy ví dụ về các hệ thống web app thường được chia thành 3 phần đó là:

    • Font-end: Là những gì phục vụ hiển thị cho người dùng cuối (giao diện, hiệu ứng…)
    • Back-end: Có chức năng tương tác với database để lấy dữ liệu, cập nhật dữ liệu, nhận và trả về dữ liệu cho font-end hiển thị.
  • Database: Là bộ phận lưu trữ dữ liệu của hệ thống, cung cấp các chức năng giúp theo tác với dữ liệu.

khong-phai-source-code-database-moi-quan-trong-nhat-trong-he-thong (2)

Vậy tại sao hệ thống database lại giảm mức độ tính toán cho các bộ phận khác? Thì đơn giản đó là các hệ quản trị cơ sở dữ liệu cung cấp các câu query (câu truy vấn), các function (hàm) giúp thao tác với dữ liệu.

Các bộ phận trung gian như hệ thống back-end chỉ cần định nghĩa các câu query, hàm và truyền xuống cho database thực hiện rồi nhận lại kết quả.

Chính vì vậy đôi khi có nhiều thao tác yêu cầu các truy vấn phức tạp thì database đã lo hết rồi. Back-end và font-end chỉ việc lấy dữ liệu đó lên để hiển thị.

Cũng từ đó việc thiết kế một cơ sở dữ liệu tốt và hiệu năng cao sẽ rất có ích cho các bộ phận khác

#3. Định hình mô hình ứng dụng

Hiện nay có rất nhiều mô hình thiết kế ứng dụng hiện đại nhưng không phải cứ thích là áp dụng được.

khong-phai-source-code-database-moi-quan-trong-nhat-trong-he-thong (3)

Một trong những nguyên nhân đầu tiên đó là do hệ thống cơ sở dữ liệu quá tập trung, không được thiết kế tốt ngay từ đầu dẫn đến khó mở rộng sau này.

Chính vì vậy, khi xây dựng các hệ thống lớn nhiều công ty đã đâu tư rất nhiều và khâu thiết kế cơ sở dữ liệu.

Vì họ hiểu được nếu cơ sở dữ liệu được thiết kế tốt thì nó sẽ định hình thiết kế cũng như giúp cho quá trình phát triển ứng dụng dễ dàng hơn sau này.

Đơn cử các bạn có thể thấy các ứng dụng lớn như Facebook, Youtube thì database của họ không phải chỉ tập trung ở một nơi mà họ chia ra rất nhiều database nhỏ và phân bố khắp nơi trên thế giới.

Lợi ích đem lại thì rõ ràng rồi, hệ thống sẽ tránh gặp tình trạng quá tải khi có quá nhiều người truy cập cùng lúc. Ứng dụng cũng có thể được chia nhỏ và phát triển sao cho phù hợp với từng đất nước, quốc gia cụ thể.

  "Làm PM, theo anh không cần biết về code, nhưng phải hiểu về SQL, database, những khái niệm cơ bản của code"
  Các thao tác cơ bản với Database SQL Server (tạo mới database, table,...)

#4. Mất rồi thì khó mà lấy lại được

khong-phai-source-code-database-moi-quan-trong-nhat-trong-he-thong (1)

Nhiều anh em sẽ bảo rằng kiểu gì người ta chả phải backup (lưu lại) dữ liệu, có mất thì cũng có backup rồi lo gì !

Đúng! nhưng ý mình ở đây là mất dữ liệu đó vào tay người khác, tổ chức hay công ty đối thủ thì coi như backup cũng chỉ còn 50% ý nghĩa mà thôi.

Dữ liệu nó không giống như mã nguồn (source code). Nếu như source code mà mất bạn có thể code lại (tuy hơi mất công) nhưng không phải là không thể.

Nhưng dữ liệu nó mang tính duy nhất và không phải bạn cứ muốn là khôi phục được nó (về mặt ý nghĩa) và cả về mặt vật lý.

Ví dụ bạn đánh mất dữ liệu của khách hàng thì sẽ rất khó để họ cung cấp lại cho bạn chứ không muốn nói là “chửi” hay “kiện” cho bạn một trận 😊

#5. Vô cùng nhạy cảm

khong-phai-source-code-database-moi-quan-trong-nhat-trong-he-thong (2)

“Nhạy cảm” có lẽ là hai từ phù hợp nhất cho việc sử dụng và lưu trữ dữ liệu, đặc biệt là dữ liệu doanh nghiệp có tính cạnh tranh cao.

Mình từng làm việc tại một công ty là đối tác cho các doanh nghiệp bán hàng và họ yêu cầu rất kỹ lưỡng trong các thao tác với dữ liệu.

Thậm chí mình còn không được làm việc trên máy cá nhân và phải làm việc trong máy ảo tại công ty để đảm bảo về an toàn thông tin, đặc biệt là an toàn về dữ liệu.

Vì những dữ liệu đó nếu bị đánh cắp và bán cho các đối tác cạnh tranh thì chắc chắn sẽ ảnh hưởng rất nhiều đến công ty.

Chưa kể cơ sở dữ liệu công ty mình được phép dùng chỉ là cơ sở dữ liệu phục vụ mục đích phát triển chứ chưa phải là cơ sở dữ liệu chính của họ.

Vì vậy mọi người phải rất thận trọng khi thao tác với dữ liệu, hạn chế các thao tác làm thay đổi dữ liệu và phải luôn có phương án dự phòng trong trường hợp không mong muốn.

#6. Lời kết

Đôi khi trong một hệ thống thông tin hay một phần mềm nào đó cái quan trọng nhất chính là dữ liệu và cách tổ chức thiết kế cơ sở dữ liệu chứ không phải là mã nguồn.

Thao tác với dữ liệu đôi khi không phải là đơn giản và bạn phải đảm bảo các thao tác của mình hạn chế làm thay đổi dữ liệu (đặc biệt là các dữ liệu nhạy cảm)

Hi vọng qua bài viết này anh em sẽ hiểu được dữ liệu và cách tổ chức dữ liệu quan trọng như thế nào. Hẹn gặp lại anh em trong các bài viết tiếp theo !

Nguyễn Đức Cảnh – Bài viết gốc tại blogchiasekienthuc.com

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

Xem thêm Việc làm it hồ chí minh hấp dẫn trên TopDev

Học như thế nào là đủ để có thể đi thực tập/fresher anh/bạn/em ơi ?

Học như thế nào là đủ để có thể đi thực tập/fresher anh/bạn/em ơi ?

Bài viết được sự cho phép của tác giả Trần Anh Tuấn

Đây là câu hỏi mình gặp khá nhiều khi nhiều bạn inbox nhờ mình tư vấn. Cho nên hôm nay mình sẽ chia sẻ cho các bạn về vấn đề này. Và đây là quan điểm và kinh nghiệm của mình thôi nhé. Mình hi vọng những điều mà mình chia sẻ sẽ giúp cho các bạn có cái tư duy tốt hơn và đỡ phải lo lắng hơn khi đi xin việc sau này nhen.

Như mình trước đây 4 5 năm trước thì phải nói là may mắn vì hồi đó đi thực tập ở công ty thì vẫn chia công việc ra là HTML CSS DeveloperJS Developer và ai làm được hết thì sẽ là Frontend Developer. Vì thế vào thời điểm đó mình mới ra trường có kiến thức HTML CSS cơ bản là đủ để đi thực tập và tìm việc. Thời gian cuối 2015 là mình ra trường đi thực tập và tới 2016 là đi xin việc ở công ty khác lúc đó mình chỉ có kiến thức HTML CSS bình thường, may mắn có biết sử dụng Photoshop cho nên mới được nhận vào làm.

>>> Xem thêm: Kinh nghiệm thực tập hay cho lập trình viên

Chưa có kiến thức gì về Javascript luôn nhé. Mình làm gần 1.5 năm rồi nghỉ, rồi 1 hay 2 năm sau đó mình mới bắt đầu tự học Javascript, trước đó toàn dùng JQuery. Thời điểm đó các Frameworks hay Libraries vẫn chưa nổi như bây giờ. Còn đến bây giờ thời thế thay đổi rồi, giờ muốn đi thực tập hay làm fresher thôi thì ít nhất các bạn phải có những kiến thức nền tảng sau đây:

  • HTML chắc chắn rồi, phải có nó để code cái sườn cho trang web của các bạn chứ
  • CSS dĩ nhiên luôn ko có nó sao mà làm giao diện đẹp được
  • Javascript phải có luôn để code các chức năng giao diện, tương tác, xử lý logic,….
  • Javascript thuần(Vanilla Javascript) làm vẫn được hết nhưng thiếu nhiều thứ, nhiều vấn đề chưa được tối ưu cho nên lúc này những Javascript FrameworksLibraries sinh ra để cứu rỗi, như ReactVue hay Angular thần thánh và vì thế hiện nay đa số các nhà tuyển dụng khi nào cũng yêu cầu 4 thứ này là HTML, CSS, JS và ít nhất 1 framework hoặc lib

Thời thế thay đổi, ngành IT giờ rất hot hơn xưa nhiều nên cạnh tranh cũng cao, các bạn phải cố gắng nhiều mới có công việc tốt được.

Bản thân mình là may mắn chứ không có giỏi, do mình may mắn làm được công ty thoải mái, sếp dễ và hiểu nhân viên + tính tự học và mày mò của mình nên mình mới được như hôm nay chứ không có giỏi gì. Bây giờ các khoá học cũng nhiều hơn trước, mình đã tự học rất nhiều nơi và mình cũng chia sẻ rất nhiều trên Blog này hoặc là Youtube của mình, cho nên khi mà mình làm khoá học thì đều chất lượng là do mình đã từng trải và biết một newbie lúc tự học là như nào cho nên mình đã làm điều đó tốt trong khoá học.

Mình có khoá học HTML CSS từ cơ bản tới nâng cao cho người mới mà mình có để banner ở trên đầu, nếu bạn muốn học để cải thiện trình độ thì có thể nhấn vào đó để ủng hộ cho mình nhen.

Đấy giờ thì ít nhất là 4 thứ đó đó, các bạn không cần phải “Master” mà hãy nắm chắc nền tảng là có thể đi thực tập, thử việc, rồi va chạm thực tế vì va chạm thực tế sẽ giúp bạn lên trình rất là nhanh luôn, biết làm việc nhóm, biết bản thân còn thiếu cái gì để bổ sung, biết deadline, áp lực ra sao khi đi làm….

>>> Xem thêm: Các cấp bậc trong ngành IT

4 thứ trên thì HTML CSS học có thể sẽ nhanh rồi từ từ luyện thành thạo sau, đến JS thì phải nắm tốt để qua Framework học cho dễ hơn và lúc đó sẽ hiểu tại sao lại cần học cái này, cái nọ…

À một điểm nữa là mình khuyên các bạn nên làm các dự án cá nhân như cắt một giao diện nào đó với HTML CSS và JS, đỉnh hơn thì làm bằng Framework hoặc Library mà các bạn theo đuổi như React chẳng hạn. Làm nhiều dự án cá nhân rồi bỏ vào CV thì khi phỏng vấn ngta tin tưởng bạn hơn là bạn không có cái gì ngoài thông tin của bạn.

Dự án thì nhiều, cắt giao diện nè, làm một trang web nghe nhạccoi phim, đọc truyện… Áp dụng toàn bộ kiến thức đã học vào, HTML CSS làm giao diện cực đẹp, Javascript tương tác xử lý cực hay, rồi React tối ưu components, routing… làm ít mà chất lượng còn hơn làm nhiều mà không cái nào ra cái nào nhé. Nhưng phải hiểu những thứ mình làm chứ đừng có lượm lặt lắp vào cho có rồi ngta phỏng vấn hỏi lại bí thì chết.

Rồi tìm hiểu các cách đưa lên mạng như GithubPagesVercel để có 1 đường dẫn hẳn hoi cho ngta truy cập vào xem và đánh giá…

Các bạn cứ mạnh dạn tự tin đi phỏng vấn, không đậu công ty này thì có thể đậu công ty khác. Đi phỏng vấn đúc kết được nhiều kinh nghiệm phỏng vấn luôn, và biết mình thiếu sót những gì để về bổ sung rất chi là hay. Chứ các bạn cứ sợ sợ không dám đi rồi riết là nhát luôn đó rồi không biết bản thân mình thiếu gì đâu, phải ra ngoài trải nghiệm thì mới thấy cần cải thiện gì, học thêm gì nhé, cứ thế rồi từ từ giỏi lên là sẽ có công việc mơ ước thôi. Mọi nỗ lực ắt sẽ có thành công thôi. Chúc các bạn may mắn và thành công sớm nhen.

>>> Xem thêm: Con đường trở thành thực tập sinh tại Google

Ah mình thấy 1 điều nữa là nhiều bạn học HTML CSS rất chi là ổn luôn nhưng qua tới Javascript thì rất sợ nó, học không vào, bị rối, nhiều vấn đề… thì đừng lo lắng, sắp tới đây mình sẽ cho ra mắt khoá học Javascript cơ bản cho người mới cực kỳ hot luôn. Đảm bảo phù hợp cho người mới như các bạn đó. Đừng quên tham khảo trên blog mình nhé.

Đừng bỏ lỡ các cơ hội việc làm cho sinh viên ngành CNTT tại TopDev. Cập nhật mới nhất về các vị trí tuyển dụng từ công ty lớn và HOT như fresher java, fresher front end, fresher tester

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

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

Xem thêm Tuyển Fresher hấp dẫn trên TopDev

Vuejs life cycle – hiểu sao cho đúng

Vuejs life cycle – hiểu sao cho đúng

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

Nếu bạn chưa nắm rõ về Vuejs Life Cycle, hãy nghe lời tôi, đọc và ghi nhớ hết các hooks trong bài viết này. Tôi thề là nó sẽ có ích cho bạn.

  Cách sử dụng các plugins jQuery trong VueJS
  Call API trong VueJS theo cách thông minh nhất

1. Creation (Initialization) – Khởi tạo component

Đầu tiên, bất cứ component nào cũng cần được khởi tạo. Các methods được thực thi ở Creation sẽ được xác nhận (perform actions) trước khi các component này được thêm vào DOM.

Nếu các bạn chưa hiểu nhiều về DOM và cách Browser render website, có thể đọc thêm bài viết này ở kieblog.vn

Hầu hết các xử lí được thực hiện ở Creation thường là thao tác giữa Client và Server (Xác thực đăng nhập, fetch data từ API). Nhưng tại sao lại thế?

Creation là bước đầu tiên trong chuỗi Vuejs life cycle, ở bước này, chúng ta chưa có quyền truy cập vào DOM tree, target mounting element (this.$el) cũng không thể truy cập

1.1 beforeCreate – trước khi tạo ra component

Before Create là sự kiện khởi đầu trong Vuejs Life Cycle, tất các các component trước khi khởi tạo đều gọi qua beforeCreate().

Chú ý rằng bất cứ dữ được nào được lấy ra ở bước này đều không ánh xạ đi đâu. Các sự kiện ở trên component cũng không work ở đây

export default {
beforeCreate() {
alert('Không có event nào được gọi trước beforeCreate!')
}
}

CHỐT: beforeCreate LUÔN ĐƯỢC GỌI VÀ GỌI ĐẦU TIÊN

1.2 created – đã tạo ra component

Ở event created, ta có thể xử lý các dữ liệu trả về từ beforeCreated. Các event handle trên component cũng có thể được xử lý ở đây.

Tuy nhiên, do các method mounted (gắn kết) và rendered (hiển thị) chưa được gọi. Không thể thực hiện các thao tác trên DOM ở bước này.

Ex: document.getElementById, byTag, …

2. Mounting (DOM Insertion) – Thao tác với DOM tree

Rõ ràng mà nói, không phải component nào cũng fetchData hay call API, xử lí dữ liệu phức tạp ở Creation event. Chính vì vậy, trong tất cả các event của Vuejs Life Cycle, event được gọi nhiều nhất luôn là Mounting.

Hãy nhớ rằng Mounting rất linh động, nó cho phép ta truy cập tới các thành phần trên DOM TRƯỚC HOẶC SAU LẦN RENDER ĐẦU TIÊN.

Vậy nếu chúng ta cần sửa đổi, truy cập tới một phần tử trước và sau khi DOM render. Các methods nên được viết ở phần mounting, còn nếu bạn muốn set data khởi tạo cho các component, các method fetch dữ liệu nên được viết ở created.

Theo kinh nghiệm riêng của mình, khi fetch hoặc update lại data ở component viết ở Mouting, không có vẻ gì là sai nhưng lúc component thay đổi data liên tục realtime. Các component sẽ giật giật tung cả chảo. =)))

vuejs-life-cycle-hooksEvent created and beforeMount

2.1 beforeMount – trước khi mount

Tất nhiên, nhìn thấy before là hiểu. Event này sẽ run trước lần render đầu tiên của component. beforeMount() cũng được gọi trước khi các điều kiện render (conditional render) trên template được gọi.

Chính vì vậy, đừng set giá trị cho các biến để kiểm tra khi render ở event này.

Ra thế, tôi mới bảo các bạn hãy nắm chắc Vuejs Life Cycle, sẽ rất dễ để biết bước nào nên làm gì?

export default {
beforeMount() {
console.log(`this.$el sẽ là undefined ở beforeMount`)
}
}

CHỐT: CÁC ELEMENT trên DOM chưa thể truy cập được ở BEFORE MOUNT

2.2 mounted – đã thao tác xong với DOM tre

Kế tiếp sau event beforeMount là mounted. Thì hoàn thành với ed ở đây cho biết rằng template và DOM đã render xong. Ta có thể truy xuất các giá trị thông qua this.$el (element).

Event này cũng thường được sử dụng để gán data cho các child component (thông qua this)

<template>
<h1>This is title, we can access it after beforeMount()</h1>
</template>

<script>
export default {
mounted() {
console.log(this.$el.textContent) // This is title, we can access it after beforeMount()
}
}
</script>

CHỐT: ở event Mounted, có thể truy cập được tới các element trên DOM.

3. Updating (Diff & Re-render) – phản ánh thay đổi và re-render lại DOM tree

Đối với component, khi có bất cứ thay đổi nào ở DOM, một element nào trên component được hiển thị lại.

3.1 beforeUpdate – trước khi cập nhật

beforeUpdate hooks sẽ chạy trước khi sự kiện update trên component bắt đầu. Một component sau khi được render lên DOM sẽ có thể được cập nhật lại.

Tất nhiên, chỉ component nào sau khi render và được cập nhật lại mới gọi tới methods này.

<script>
export default {
data() {
return {
firstTimeItem: "Firsttime"
}
},

beforeUpdate() {
console.log(this.firstTimeItem) // Mỗi lần upadte sẽ gọi tới method này
},

created() {
setInterval(() => {
this.firstTimeItem = "Yo bro, i want to update"
}, 1000)
}
}
</script>

3.2 updated – sau khi update

Trong Vuejs Life Cycle, event updated sẽ bắt đầu chạy sau khi CÔNG VIỆC RENDER NỘI DUNG UPDATE TRÊN DOM hoàn tất.

Nếu ta muốn thao tác thay đổi trên DOM tree sau khi nội dung đã update thì thực hiện ở updated là an toàn nhất. Nguyên nhân là vì updated chỉ được gọi sau khi DOM đã update xong.

<template>
<p ref="dom-element">{{counter}}</p>
</template>
<script>
export default {
data() {
return {
counter: 0
}
},

updated() {
// Được gọi sau khi DOM update. Giá trị luôn bằng giá trị tăng của counter
console.log(+this.$refs['dom-element'].textContent === this.counter)
},

created() {
setInterval(() => {
this.counter++
}, 1000)
}
}
</script>

4. Destruction (Teardown) – hủy bỏ

Destruction hooks là những actions cho phép ta handle sự kiện hủy bỏ các component. Thực hiện trước khi component được khóa khỏi cây DOM.

4.1 beforeDestroy – trước khi hủy

Ở event này, trước khi nó được gọi, component vẫn có đầy đủ các thành phần (present) và chứng năng (functional). Nếu một event hoặc một variable gây tốn kém về bộ nhớ (nếu không được dọn dẹp sau khi khởi tạo), ta có thể xử lý chúng ở đây.

<script>
export default {
data() {
return {
variableLeakMem: 'When component destroy, please remove me'
}
},

beforeDestroy() {
// Loại bỏ variable hay các event listening sẽ đỡ lãng phí bộ nhớ
this.variableLeakMem = null
delete this.variableLeakMem
}
}
</script>

4.2 destroyed – đã hủy component

Event destroyed hooks trong Vuejs life cycle đóng vai trò là event kiểm chứng cho những gì đã destroy ở beforeDestroy. Ở event này, tất cả các đối tượng, các event đã bị hủy bỏ ở beforeDestroy sẽ không còn nữa

<script>
import MyCreepyAnalyticsService from './somewhere-bad'

export default {
destroyed() {
console.log(this) // There's practically nothing here!
MyCreepyAnalyticsService.informService('Component destroyed. All assets move in on target on my mark.')
}
}
</script>

CHỐT: EVENT DESTROY CÓ THỂ DÙNG ĐỂ KIỂM CHỨNG CHO VIỆC MUỐN DESTROY CÁC ĐỐI TƯỢNG MONG MUỐN.

5. Hãy nắm chắc Vuejs Life Cycle

Qua bài viết này, mong các bạn sẽ hiểu thêm về Vuejs Life Cycle. Hiểu rõ về cycle sẽ giúp chúng ta xử lý tốt trên các page hoặc component.

vuejs-life-cycle-hooksLưu ý rằng life cycle có thể khác biệt giữa các phiên bản của Vuejs nhé

Nếu bug phát sinh, cũng dễ dàng xử lí (vì chúng ta biết nó xuất hiện ở step nào). Sắp tới sẽ có một loạt bài viết về Vuejs. Mời các bạn đón đọc. Chân thành cảm ơn!.

6. Reference – tham khảo

Nếu đã quen với Vuejs, hãy tìm hiểu thêm về React. Đối thủ không đội trời chung của Vuejs.

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

Kiến trúc một khối (Monolithic)

kiến trúc một khối

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

Trong quá khứ, người ta xây dựng hệ thống theo một khối (Monolithic Applications). Ứng dụng phần mềm doanh nghiệp được thiết kế để đáp ứng nhiều yêu cầu kinh doanh của doanh nghiệp. Do đó, các phần mềm cung cấp hàng trăm các tính năng và tất cả những tính năng này đều được gói trong một ứng dụng monolithic. Ví dụ, ERPs, CRMs hay nhiều phần mềm khác chứa hàng trăm tính năng. Việc triển khải, sử lỗi, mở rộng và nâng cấp những phần mềm khổng lồ này trở thành một cơn ác mộng.

  10 điều mọi nhà phát triển ứng dụng Android nên biết về kiến trúc Architecture
  20+ nguồn tuyển dụng và chia sẻ kiến thức IT hiệu quả trên Facebook

Thử tưởng tượng bạn đang phải xây dựng một dịch vụ gọi taxi qua di động nhằm cạnh tranh với Uber và Grab. Sau một số buổi họp thu thập yêu cầu và phân tích thiết kế, bạn sẽ chọn công nghệ (technology stack) rồi tạo dự án bằng các framework đại loại như Rails, Spring Boot, Play. Dự án này sẽ có kiến trúc chia khối lục giác (hexagol architecture) hay tổng quát hơn là khối đa diện. Kiến trúc đa diện giúp ứng dụng chuyên biệt mô hình dữ liệu.

Graph-01-e1431978090737

Nhìn vào lõi của ứng dụng, ta thấy business logic được thể hiện bởi các khối dịch vụ (services), đối tượng cho từng vùng nghiệp vụ (domain objects) và các sự kiện (events). Xung quanh lõi là các adapter để kết nối vào cơ sở dữ liệu, gửi nhận message, web service hoặc front-end web application.

Mặc dù có cấu trúc module hóa hợp lý, nhưng ứng dụng kiểu này sẽ đóng gói và cài đặt thành một khối (monolithic). Cách để triển khai gói ứng dụng tùy thuộc vào ngôn ngữ lập trình hay thư viện framework. Ví dụ ứng dụng sử dụng Spring framework, đóng trong file WAR, triển khai trên application server như Tomcat hay Jetty. Dùng framework khác, ví dụ Spring Boot thì ứng dụng Java là một file tự đóng gói để chạy là JAR. Ứng Rails hay Node.js đóng gói theo cấu trúc thư mục phân cấp.

Ứng dụng viết kiểu này cực kì phổ biến. Chúng hoàn toàn dễ phát triển, đặc biệt cùng với sự phát triển của IDE và những tool khác tập trung vào xây dựng những ứng dụng đơn lẻ dựa trên template sẵn có. Tại sao lại vậy? Đơn giản thôi, do họ cần thuyết phục lập trình viên đi theo công nghệ/framework nên nhà sản xuất phải làm sao lập trình chỉ cần New Project, ấn nút Build & Run là ứng dụng chạy được ngay và luôn. Bạn có thể dễ dàng thực hiện testing bằng cách chạy ứng dụng và thực hiện test UI bằng Selenium. Ứng dụng một khối như thế này khá dễ triển khai. Đơn giản là chỉ cần copy gói được build ra lên server. Thêm nữa, những ứng dụng dạng này cũng có thể dễ dàng scale bằng cách chạy nhiều instance được phân tải bằng load balancer. Trong giai đoạn đầu sau khi triển khai, chúng hoạt động vô cùng tốt.

Từng bước xuống địa ngục.

Đáng tiếc rằng, cách tiếp cận kiến trúc một khối tuy dễ dàng nhưng lại bộc lộ nhiều khiếm khuyết.

Ứng dụng của bạn thành công, kéo theo đó số lượng người dùng tăng, yêu cầu tính năng mới tăng, dữ liệu tăng, logic phức tạp hơn, giao tiếp với hệ thống khác tăng, và hàng trăm thứ khác dẫn đến một kết quả là ứng dụng phình to ra một cách khủng khiếp. Sau mỗi sprint, hàng loạt tính năng mới được thêm vào, thêm code, thêm bảng, thêm logic… Chỉ sau một thời gian, ứng dụng đơn giản sẽ trở nên kềnh càng như một con quái vật. Và số lượng effort bỏ ra để phát triển cũng như bảo trì con quái vật này sẽ không hề nhỏ.

Khi ứng dụng phình quá to, mọi nỗ lực tối ưu, áp dụng agile method đều không còn hiệu quả. Chỉ một chỉnh sửa nhỏ, sẽ phải tham chiếu đến những chỗ nó sử dụng để xem xét sự ảnh hưởng của nó lên toàn bộ hệ thống. Nó quá khó để cho một lập trình viên có thể nắm và hiểu toàn bộ code hệ thống. Và như một hệ quả tất yếu, việc fix bug, hay thêm tính năng mới trở nên khó hơn và tốn nhiều thời gian hơn.

Trong ứng dụng một khối, sự chặt chẽ là ưu điểm tự nhiên xuất phát từ kiến trúc, nhưng nó tiềm ẩn nguy cơ ràng buộc cứng nhắc (tight coupling). Chi phí, thời gian, nỗ lực phát triển, sửa lỗi, kiểm thử một chức năng sẽ tăng tỷ lệ cấp số nhân theo độ lớn của ứng dụng.

Khi ứng dụng càng lớn, mỗi lần deploy phiên bản mới cũng sẽ là một cực hình, thậm chí tệ hại nếu thời gian down time cho việc khởi động lại là quá lớn. Điều này cũng ảnh hưởng khi lập trình viên đang debug ứng dụng, tưởng tượng một ứng dụng redeploy mất 10 phút thì trong 10 phút đó lập trình viên sẽ làm gì, rõ rành nó ảnh hưởng rất lớn đến năng suất làm việc.

Gần đây, bạn nghe nói nhiều hơn về khái niệm triển khai đều đặn (continous deployment). Những ứng dụng SaaS (Software application as Service) tiên tiến, cần phải cập nhật vài lần trong một ngày. Quá khó để triển khai lại cả một ứng dụng cực lớn chỉ vì một số nâng cấp nhỏ. Hoạt động bị ngưng trệ, kiểm thử lại sau triển khai sẽ lâu công hơn. Kết quả là việc này sẽ khó mà áp dụng với ứng dụng một khối. Nếu không muốn nói là không thể.

Ngoài ra, thật khó để scale khi mà những module khác nhau, với những nhu cầu về tài nguyên khác nhau nằm chung trong một khối. Ví dụ, triển khai ứng dụng trên AWS (Amazon Web Services), bạn có một module xử lý ảnh, module này tốn tài nguyên CPU khá lớn, thích hợp nêú bạn sử dụng EC2 Compute Optimized instances, ngoài ra, bạn lại có một module sử dụng caching in-memory với nhu cầu tài nguyên về RAM là vô cùng lớn, thích hợp hơn nếu bạn sử dụng EC2 Memory-optimized instances. Tuy nhiên vì là ứng dụng một khối nên chúng ta phải tính toán làm sao cho phù hợp nhất, điều này cũng ảnh hưởng không nhỏ đến chi phí bỏ ra.

Một vấn đề khác với các ứng dụng nguyên khối đó là độ tin cậy. Bởi vì tất cả các module đang chạy trong cùng một quá trình, một lỗi trong bất kỳ module nào, chẳng hạn như một lỗi memory leak, cũng có thể có khả năng làm down toàn bộ quá trình cũng như cả hệ thống.

Cuối cùng, ứng dụng một khối sử dụng một ngôn ngữ, một framework duy nhất vì thế lập trình viên làm việc trong dự án sẽ quen với sự thuận tiện, dễ dàng khi chỉ cần nắm sâu một ngôn ngữ, một công cụ có thể giải quyết hầu hết vấn đề. Họ dần lệ thuộc vào ngôn ngữ đó và trở nên thiên vị, ngại cởi mở, tích hợp với những công nghệ khác của ngôn ngữ khác. Thậm chí khi framework hay ngôn ngữ có nhược điểm cố hữu, vì tính một khối của ứng dụng sẽ bó buộc lập trình viên thử nghiệm đưa vào thay đổi đột phá ngoại lai.

Đơn giản thế này thôi, ứng dụng một khối có hơn 2 triệu dòng code trên framework XYZ nào đó, liệu đội bạn có đủ dũng cảm, nguồn lực để viết lại toàn bộ trên framework ABC mới hơn, tốt hơn. Dù cho bạn có đội ngũ lập trình giỏi, sáng tạo thì họ cũng không hề muốn làm trong dự án bế tắc kiểu này. Hoặc nếu bạn thật sự muốn làm thì chi phí để đập đi xây lại toàn bộ hệ thống là vô cùng lớn. Tình trạng giữ thì khổ, xây thì khó, khiến dịch vụ, sản phẩm của bạn ngày càng khó phát triển.

Tóm lại, bám vào kiến trúc một khối, một vé xuống địa ngục là cao hơn lên thiên đường.

Đây là bài viết trong loạt bài viết về “Tổng quan về sự phát triển của kiến trúc phần mềm“. Đây là loạt bài viết chủ yếu giới thiệu về một số mô hình kiến trúc phần mềm hay nói đúng hơn là sự phát triển của chúng qua từng giai đoạn, qua đó giúp chúng ta có cái nhìn tổng quát, up-to-date và là roadmap để bắt đầu hành trình chinh phục (đào sâu) thế giới của những bản thiết kế với vai trò là những kỹ sư và kiến trúc sư phần mềm đam mê với nghề.

Bài viết được tham khảo từ:

Nguồn: https://codeaholicguy.com/2015/11/13/gioi-thieu-ve-microservices-phan-1-dia-nguc-kien-truc-mot-khoi/

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 các vị trí it job hấp dẫn trên TopDev

Để học tốt Python

Để học tốt Python

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

Python là một trong những ngôn ngữ lập trình linh hoạt và được sử dụng rộng rãi nhất trên thế giới. Đối với những nhà lập trình mới thì Python cực kỳ thông dụng và mang lại cho họ cơ hội tham gia vào nhiều lĩnh vực coding như mong muốn.

Tuy nhiên nhiều tài liệu giảng dạy về Python hiện nay lại khá nhạt nhẽo và chung chung. Điều này có thể khiến bạn gặp khó khăn trong việc học Python đặc biệt là đối với người mới bắt đầu. Đó là lý do tại sao chúng tôi sẽ cung cấp từng bước trong hướng dẫn này để chỉ cho bạn cách tốt nhất để học Python.

Hãy cùng bắt đầu bằng việc tìm hiểu những điều cơ bản, ngắn gọn để bạn có cái nhìn tổng quan về ngôn ngữ lập trình Python và nó được sử dụng để làm gì. Sau đó, chúng ta sẽ tiếp tục tìm hiểu xem cách học Python như thế nào và những điều cần phải làm khi mới bắt đầu học. Chúng tôi sẽ chỉ cho bạn về các nguồn hướng dẫn Python tốt nhất mà bạn có thể rút ra trong quá trình học, và cách để tiếp tục phát triển khi bắt đầu học lên cao.

Hy vọng bạn sẽ thích hướng dẫn này!

Xem thêm: Tìm việc làm python lương cao

Bước 1: Python là gì? và Python dùng để làm gì?

Trước khi học lập trình Python thì bạn cần phải biết nó là gì và tại sao nó được sử dụng. Nói một cách đơn giản, Python là một ngôn ngữ lập trình cấp cao, cực kỳ linh hoạt, có thể được sử dụng cho hầu hết mọi thứ mà không yêu cầu một ngôn ngữ cụ thể. Một số tính năng khiến Python trở nên thông dụng bao gồm:

Cú pháp Python rất đơn giản chính vì vậy mà nó khá dễ sử dụng. Một số người cho rằng cách tốt nhất để học Python cơ bản là bắt đầu viết luôn chương trình. Hầu hết những cú pháp Python có tính logic cao đủ để giúp bạn bắt đầu viết được luôn chương trình của mình.
Hầu hết những nhà lập trình viên cho rằng Python là một ngôn ngữ dễ học và nó được giảng dạy phổ biến nhất trong các trường học trên toàn thế giới.
Python thực sự có công dụng cực kỳ lớn và bạn sẽ có thể làm khá nhiều thứ với nó đó.
Những tính năng trên đã khiến Python trở nên phổ biến trên toàn thế giới. Nó được sử dụng trong nhiều lĩnh vực khác nhau như:

  • Phát triển trang web Back-end
  • Phát triển trò chơi.
  • Khoa học dữ liệu và phân tích.
  • Phát triển ứng dụng di động.
  • Robot và AI (Trí tuệ nhân tạo)
    Nếu bạn có ước mơ làm việc với một trong những lĩnh vực này, thì đây chính là lúc để bạn khám phá cách tốt nhất để học Python!

Bước 2: Đăng ký một khóa học Python trực tuyến

Có lẽ là bạn sẽ cho rằng khóa học trực tuyến hướng dẫn Python khá là chung chung, nhàm chán và không có nội dung gì sâu xa. Tuy nhiên, với những năm kinh nghiệm hướng dẫn những bước này thì tôi tin rằng tôi đang chỉ cho bạn cách tốt nhất để học lập trình Python.

Các khóa học trực tuyến là một nguồn tài nguyên thường bị đánh giá thấp so với khả năng đáng kinh ngạc của chúng. Trong thế giới hiện đại, không cần thiết phải học đại học hay khóa học về khoa học máy tính để trở thành lập trình viên. Tôi tin rằng các khóa học trực tuyến lại là một cách tốt hơn để học lập trình Python. Bởi vì chúng có một số công dụng đáng kinh ngạc như sau:

  • Các khóa học trực tuyến cho phép học theo lịch trình của riêng bạn, nó phù hợp cho những người đang đi làm giờ hành chính hoặc có những công việc khác.
  • Các khóa học trực tuyến sẽ bao quát được kiến thức một cách rõ ràng, dễ hiểu và súc tích.
  • Các khóa học trực tuyến cho phép quay lại các khái niệm và phần khó của khóa học bao nhiêu lần tùy thích.
    Tuy nhiên, bạn cũng cần phải rèn luyện cho mình tinh thần tự giác và có động lực để học một khóa học trực tuyến. Không có việc bị giới hạn thời gian hoặc ngày trả bài có thể sẽ khiến bạn không kiên trì để tiếp tục được, vì vậy hãy luôn nhắc nhở bản thân về việc học của mình.

Và với nhiều năm kinh nghiệm trong lĩnh vực này, uCode.vn tin rằng khóa học của chúng tôi là một sự lựa chọn tuyệt vời cho bạn.

  Python và cách tiết kiệm dung lượng cho phần mềm nhúng

Bước 3: Cài đặt Python vào máy tính

  • Bạn có thể bỏ qua bước này nếu bạn có máy tính Apple. Với máy tính Apple thì Python đã được cài đặt sẵn. Còn đối với máy tính với hệ điều hành Windows thì không có.

Nếu sử dụng Python với Windows, thì bạn sẽ cần tải xuống và cài đặt nó vào máy tính của mình. Có hai phiên bản chính của Python: Python 2 và Python 3. Lựa chọn phiên bản nào là phụ thuộc vào nhu cầu sử dụng của bạn.

Trong hầu hết các trường hợp, tốt nhất là nên tải xuống cả hai phiên bản. Có nhiều chương trình cũ được xây dựng bằng Python 2 thì sẽ không chạy với Python 3. Tuy nhiên, phiên bản mới lại cung cấp rất nhiều cải tiến hơn so với phiên bản cũ hơn và thuận lợi cho những người tìm kiếm để học Python.

Cài đặt Python:
Để cài đặt Python trên máy tính của bạn, bạn sẽ cần phải truy cập vào trang để tải Python xuống. Điều đầu tiên mà bạn nhận thấy là có hàng trăm phiên bản khác nhau. Cách tốt nhất là bạn nên tải phiên bản mới nhất để học ngôn ngữ và làm quen với cú pháp chính của Python. Làm theo lời những hướng dẫn và thực hiện cài đặt Python như bất kỳ chương trình nào khác.

Sau khi đã hoàn tất cài đặt thì bây giờ chúng ta đã sẵn sàng để chuyển sang bước tiếp theo!

Bước 4: Tìm hiểu thêm với các nguồn tài liệu khác

Khi đã cài đặt thành công Python và tiến hành học trên khóa học trực tuyến thì bạn có thể tham khảo thêm về Python thông qua những nguồn tài liệu khác. Mặc dù dưới đây không có nguồn tài liệu nào có thể tự dạy bạn Python, nhưng tất cả chúng đều có thể nâng cao kiến thức và giúp bạn có thêm trải nghiệm học tập. Một số nguồn tài liệu tốt nhất được rút ra trong quá trình tìm cách tốt nhất để học Python bao gồm:

Hướng dẫn tham khảo
Nếu bạn thực sự nghiêm túc muốn tìm ra cách tốt nhất để học Python, thì bạn cần quan tâm, chú ý đến tài liệu khảo chất lượng. Tài liệu tham khảo sẽ trở thành một trong những công cụ có giá trị nhất trong suốt sự nghiệp của một lập trình viên. Tài liệu tham khảo ngôn ngữ Python chính thức cung cấp những giải thích rõ ràng về cú pháp, quy ước và những thực tiễn tốt nhất về lập trình. Nó cho phép bạn tìm kiếm các khái niệm khó hoặc những vấn đề mà bạn đang gặp phải. Khi được khai thác đúng cách thì tài liệu tham khảo sẽ giúp bạn tăng tốc tiến trình coding của mình.

Video trên YouTube
Xem những video YouTube cũng là cách tuyệt vời để làm sáng tỏ những vấn đề khó trong lập trình. Khi gặp khó khăn thì nhiều người đã chọn cách tìm kiếm ngay trên Youtube. Một cuộc khảo sát nhanh cho thấy khi có điều gì cần phải giải đáp thì bạn sẽ thường tìm kiếm hàng loạt các video khác nhau có chủ đề liên quan, chọn một video có đánh giá cao và nhiều lượt theo dõi rồi xem nó. Ngoài ra, bạn có thể đăng ký kênh youtube để không bỏ lỡ những video hướng dẫn mới ra nhất. Hãy tận dụng và khai thác tốt điều đó.

Diễn đàn trực tuyến
Những diễn đàn học về coding trực tuyến cũng là một nơi tuyệt vời để nhận sự trợ giúp khi bạn bị mắc kẹt trong một khái niệm hoặc ý tưởng nào đó. Tôi thường tìm đến các diễn đàn trực tuyến khi có những vấn đề coding mà không thể hiểu được. Viết một bài đăng ngắn trình bày về vấn đề bạn gặp phải với loại mã code bạn thực hiện.

  20 tài liệu học Python thiết thực để trở thành lập trình viên chuyên nghiệp

Bước 5: Tìm hiểu các Framework

Framework là các chương trình được thiết kế để cho việc lập trình trở nên dễ dàng hơn. Khi nói đến Python cơ bản, hầu hết các khung được thiết kế để phát triển web. Chúng có thể được sử dụng để giúp phát triển các ứng dụng web nhanh hơn, đảm bảo mã code thực hiện tốt nhất và giúp bạn có thêm thời gian tập trung vào việc khác. Nếu muốn trở thành một nhà phát triển Python thì hãy nên bắt đầu làm quen với các framework phổ biến nhất như:

  • Django – Django là một khung phát triển web đầy đủ, miễn phí, mã nguồn mở, Django được các nhà phát triển trên toàn thế giới sử dụng. Nó được sử dụng với mục đích cung cấp mọi thứ mà nhà phát triển cần thay vì tìm kiếm trên thư viện.
  • Flask – Flask là một khung phát triển nhỏ hơn được thiết kế để tạo ra một nền tảng ứng dụng chất lượng cao cho website của bạn. Mô-đun (modular) cho phép sử dụng các phần mở rộng khi cần thiết, bao gồm một loạt các tính năng vượt trội, thú vị mà cực kỳ hữu ích.
  • Pyramid – Pyramid cũng tương tự như Django, nhưng nó đơn giản và dễ sử dụng hơn. Nó tương thích với ứng dụng ở mọi quy mô chính vì vậy đã khiến nó trở nên thông dụng trên toàn thế giới.
    Đây chỉ là một vài trong số các Python framework phổ biến nhất. Không nhất thiết phải học tất cả tính năng của tất cả chúng. Thay vào đó, bạn chỉ cần cố gắng làm quen về cách sử dụng và những tính năng chính của chúng mà thôi.

Bước 6: Bắt đầu xây dựng chương trình

Khi đã tìm ra được cách để học lập trình Python với nhu cầu của mình thì bạn cần phải lĩnh hội được khá tốt kiến thức về Python cơ bản. Sau đó thì hãy bắt tay vào tìm hiểu cách tạo ra chương trình của chính mình. Đây chính là cơ hội tốt nhất để bắt đầu thực hành công việc viết code của mình.

Theo kinh nghiệm của tôi, một trong những cách tốt nhất để học Python là thực hành dựa trên những kiến thức đã có bằng cách viết chương trình. Hãy bắt đầu với những chương trình đơn giản. Đừng quá lo lắng hay dồn thời gian để tạo ra những chương trình, trò chơi, phần mềm quá khó mà nên tập trung vào việc viết các đoạn code nhỏ. Hãy theo dõi những bước hướng dẫn dưới đây để bắt đầu thực hiện chương trình đầu tiên của bạn:

Brainstorm ý tưởng cho các chương trình Python đơn giản. Hãy thử viết chúng ra, chọn một vài ý tưởng có vẻ thú vị mà bạn cho rằng bạn có đủ kiến thức để thực hiện nó.
Bắt đầu viết code cho chương trình. Chú ý một điều là bạn hãy kiểm tra chắc chắn để nhận ra những lỗi trước khi chúng gây ra vấn đề lớn. Để tránh những điều nhầm lẫn thì bạn nên viết ra kế hoạch chi tiết các bước cần thực hiện cho việc viết chương trình của mình.
Khi đã hoàn thành chương trình của mình, hãy xem lại và đảm bảo bạn có thể giải thích những gì đã làm. Bạn có thể gửi phần viết code của mình lên trên một diễn đàn trực tuyến và nhờ mọi người đóng góp ý kiến.
Như vậy, chương trình đầu tiên của bạn cơ bản đã thành công. Chắc chắn sẽ có những sai sót, tuy nhiên bạn nên chú ý đến những điểm thiếu sót đó để tiếp tục cải thiện khi viết một chương trình khác sắp tới.

Xem thêm việc làm python Hồ Chí Minh mới nhất

Bước 7: Học Python thông qua việc hiểu những lỗi code

Bạn nên tìm hiểu hay học về những mã code sai trong quá trình học hỏi lập trình Python. Theo tôi, hiểu được lỗi code cũng là một cách tốt để học Python. Nếu không biết một lỗi cụ thể có nghĩa là gì hoặc cách khắc phục nó thì bạn sẽ không thể khắc phục sự cố đó tốt vào những chương trình khác được.

Nếu như bạn chưa tìm hiểu về các lỗi Python phổ biến, thì bạn nên dành thời gian tìm hiểu và làm quen với chúng ngay bây giờ thông qua trang web Python về đầy đủ các loại lỗi và cách khắc phục chúng.

Hãy nhớ rằng, nếu bạn đã cố gắng tìm kiếm mãi mà không có được câu trả lời cho một vấn đề nào đó thì hãy tận dụng sự hiểu biết của những người khác thông qua những diễn đàn để họ có thể hỗ trợ bạn!

Bước 8: Tạo động lực và thử thách bản thân mỗi ngày

Nếu bạn nghiêm túc về việc học Python từ mới bắt đầu và mong muốn trở thành một lập trình viên chuyên nghiệp, thì bạn cần tiếp tục trau dồi hàng ngày. Tôi thích thử thách bản thân mỗi ngày để học được điều mới và tiếp tục duy trì kiến thức đã học để trở thành một lập trình viên Python giỏi hơn. Có rất nhiều cách khác nhau để thử thách bản thân hàng ngày, với tôi chúng bao gồm:

Hack mã Code
Tôi thấy rằng việc tải xuống và làm việc với mã code của người khác cũng là một cách khá tốt để tìm hiểu Python. Tôi thích đi đến một trang web như GitHub và tìm một số mã nguồn mở có vẻ thú vị. Tải xuống tệp mã code đó, mở nó trong mã code hoặc trình soạn thảo văn bản và tìm hiểu nó từ từ. Hãy cố gắng để hiểu tất cả các cú pháp và mỗi dòng mã code có nhiệm vụ gì. Ghi chú những điều cần thiết, và sửa lại chúng nếu bạn có thể.

Hỗ trợ những người khác
Một cách tuyệt vời khác để học các kỹ năng Python mới là giúp đỡ người khác. Đi đến diễn đàn về coding yêu thích của mình, tìm ai đó đang cần trợ giúp và hướng dẫn họ. Nếu trong khả năng thì hãy thử và giúp họ giải quyết vấn đề. Điều này sẽ giúp bạn trở thành một lập trình tốt hơn và giúp bạn cải thiện kỹ năng giải quyết vấn đề.

Hoàn thành một thử thách Coding
Thử thách coding rất thú vị, hấp dẫn và chúng buộc bạn phải suy nghĩ rộng hơn. Một tìm kiếm nhanh của Google sẽ giúp ta thấy một loạt các trang web cung cấp các thử thách coding. Trong hầu hết các trường hợp, bạn sẽ được cung cấp các hướng dẫn chi tiết và được yêu cầu tạo một chương trình thực hiện những điều mong muốn.

Cách tốt nhất để học Python – Kết luận

Học một ngôn ngữ lập trình mới có thể gặp nhiều khó khăn. Tuy nhiên, với hướng dẫn theo từng bước đã được thiết kế kỹ lưỡng này sẽ giúp khám phá cách tốt nhất để học Python theo nhu cầu của bạn. Tôi đã trả lời các câu hỏi liên quan đến ‘cách học python như thế nào’ dựa trên một số nguồn tài liệu và phương pháp học tập yêu thích của tôi. Cuối cùng, tôi đã giới thiệu một số cách tốt nhất để thúc đẩy tiến trình học tập của bạn.

Tôi nghĩ rằng hướng dẫn này đã chỉ ra cách tốt nhất để học Python nhanh nhất có thể. Bắt đầu bằng cách thực hiện một số nghiên cứu về Python, nó là gì và bạn có thể làm gì với nó. Đăng ký một khóa học trực tuyến dạy các kiến thức Python cơ bản và thực hành cho đến khi nhuần nhuyễn với các cú pháp và khái niệm chính.

Khám phá các nguồn tài liệu khác nhau – chẳng hạn như những tài liệu hướng dẫn tham khảo và video – và tìm hiểu cách sử dụng chúng để đạt hiệu quả tối đa. Tìm hiểu về lỗi code và framework, sau đó bắt đầu tạo các chương trình đơn giản. Hãy nhớ thực hành thường xuyên nhất có thể và tập trung vào việc học những điều mới mỗi khi bạn viết code bằng Python.

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

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

Xem thêm việc làm ngành IT hấp dẫn trên TopDev

Vue.js là gì?

Vue.js là gì?

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

 Vue.js trong lập trình website quan trọng như thế nào?

Xin chào tất cả anh em đam mê ngành công nghệ thông tin. Chắc hẳn là anh em ít khi thấy người ta chia sẻ nhiều về bất cứ tài liệu nào nói về framework của vue.js. Hôm nay viết mã bug sẽ chia sẻ cơ bản về nó nhé. Nhưng trước khi muốn học được nó thì ae phải biết qua htm, css, javascript một chút đã nhé.

  Mẫu cú pháp câu lệnh trong Vue.js
  3 phút làm quen với Vue.js

Giới thiệu Vue.js là gì?

Vue (phát âm là / vjuː /, like view ) là một khung tiến bộ để xây dựng giao diện người dùng. Không giống như các framework nguyên khối khác, Vue được thiết kế từ đầu để có thể áp dụng dần dần. Thư viện lõi chỉ tập trung vào lớp xem và dễ dàng lấy và tích hợp với các thư viện khác hoặc các dự án hiện có. Mặt khác, Vue cũng hoàn toàn có khả năng cung cấp năng lượng cho các Ứng dụng Trang đơn khi được sử dụng kết hợp với các công cụ hiện đại và các thư viện hỗ trợ .

Nếu bạn muốn tìm hiểu thêm về Vue trước khi đi sâu vào, chúng tôi đã tạo một video hướng dẫn về các nguyên tắc cốt lõi và một dự án mẫu.

Nếu bạn là một nhà phát triển giao diện người dùng có kinh nghiệm và muốn biết Vue so với các thư viện / khung công tác khác như thế nào. Hướng dẫn cài đặt:

Hướng dẫn chính thức giả định kiến ​​thức trình độ trung cấp về HTML, CSS và JavaScript. Nếu bạn là người hoàn toàn mới với việc phát triển giao diện người dùng, có thể không phải là ý tưởng tốt nhất nếu bạn nhảy ngay vào một khuôn khổ như bước đầu tiên của bạn – hãy nắm bắt những điều cơ bản sau đó quay lại! Kinh nghiệm trước với các khuôn khổ khác sẽ giúp ích, nhưng không bắt buộc.

Cách dễ nhất để dùng thử Vue.js là sử dụng ví dụ Hello World . Vui lòng mở nó trong một tab khác và làm theo khi chúng ta xem qua một số ví dụ cơ bản. Hoặc, bạn có thể tạo một index.htmltệp và bao gồm Vue với:

<!-- development version, includes helpful console warnings -->

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

hoặc là:

<!-- production version, optimized for size and speed -->

<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

Các cài đặt trang cung cấp nhiều tùy chọn cài đặt Vue. Lưu ý: Chúng tôi không khuyên người mới bắt đầu nên bắt đầu vue-cli, đặc biệt nếu bạn chưa quen với các công cụ xây dựng dựa trên Node.js.

Nếu bạn thích thứ gì đó tương tác hơn, bạn cũng có thể xem loạt bài hướng dẫn này trên Scrimba , cung cấp cho bạn sự kết hợp giữa video màn hình và sân chơi mã mà bạn có thể tạm dừng và phát lại bất cứ lúc nào.

Cốt lõi của Vue.js là một hệ thống cho phép chúng tôi kết xuất dữ liệu một cách khai báo tới DOM bằng cách sử dụng cú pháp mẫu đơn giản:

<div id="app">

  {{ message }}

</div>

var app = new Vue({

  el: '#app',

  data: {

    message: 'Hello Vue!'

  }

})

Chúng tôi đã tạo ứng dụng Vue đầu tiên của mình! Điều này trông khá giống với việc kết xuất một mẫu chuỗi, nhưng Vue đã thực hiện rất nhiều công việc. Dữ liệu và DOM hiện đã được liên kết và mọi thứ hiện đã hoạt động . Làm sao mà chúng ta biết được? Mở bảng điều khiển JavaScript của trình duyệt của bạn (ngay bây giờ, trên trang này) và đặt app.messagethành một giá trị khác. Bạn sẽ thấy ví dụ được hiển thị ở trên cập nhật tương ứng.

Lưu ý rằng chúng ta không còn phải tương tác trực tiếp với HTML nữa. Một ứng dụng Vue tự gắn chính nó vào một phần tử DOM duy nhất ( #apptrong trường hợp của chúng tôi) sau đó kiểm soát hoàn toàn nó. HTML là điểm nhập của chúng tôi, nhưng mọi thứ khác xảy ra trong phiên bản Vue mới được tạo.

Ngoài nội suy văn bản, chúng ta cũng có thể ràng buộc các thuộc tính phần tử như sau:

<div id="app-2">

  <span v-bind:title="message">

    Hover your mouse over me for a few seconds

    to see my dynamically bound title!

  </span>

</div>

var app2 = new Vue({

  el: '#app-2',

  data: {

    message: 'You loaded this page on ' + new Date().toLocaleString()

  }

})

Ở đây chúng tôi đang gặp một cái gì đó mới. Các v-bindthuộc tính mà bạn đang nhìn thấy được gọi là một chỉ thị . Các chỉ thị có tiền tố là v-để chỉ ra rằng chúng là các thuộc tính đặc biệt do Vue cung cấp và như bạn có thể đoán, chúng áp dụng hành vi phản ứng đặc biệt cho DOM được hiển thị. Ở đây, về cơ bản nó đang nói “giữ cho titlethuộc tính của phần tử này được cập nhật với thuộc messagetính trên phiên bản Vue.”

Nếu bạn mở lại bảng điều khiển JavaScript và nhập app2.message = ‘some new message’, một lần nữa bạn sẽ thấy rằng HTML liên kết – trong trường hợp này là titlethuộc tính – đã được cập nhật.

Cũng dễ dàng chuyển đổi sự hiện diện của một phần tử:

<div id="app-3">

  <span v-if="seen">Now you see me</span>

</div>

var app3 = new Vue({

  el: '#app-3',

  data: {

    seen: true

  }

})

Hãy tiếp tục và nhập app3.seen = falsevào bảng điều khiển. Bạn sẽ thấy thông báo biến mất.

Ví dụ này chứng minh rằng chúng ta có thể liên kết dữ liệu không chỉ với văn bản và thuộc tính mà còn với cấu trúc của DOM. Hơn nữa, Vue cũng cung cấp một hệ thống hiệu ứng chuyển tiếp mạnh mẽ có thể tự động áp dụng các hiệu ứng chuyển tiếp khi các yếu tố được Vue chèn / cập nhật / loại bỏ.

Có khá nhiều chỉ thị khác, mỗi chỉ thị có chức năng đặc biệt riêng. Ví dụ, v-forchỉ thị có thể được sử dụng để hiển thị danh sách các mục bằng cách sử dụng dữ liệu từ Mảng:

<div id="app-4">

  <ol>

    <li v-for="todo in todos">

      {{ todo.text }}

    </li>

  </ol>

</div>

var app4 = new Vue({

  el: '#app-4',

  data: {

    todos: [

      { text: 'Learn JavaScript' },

      { text: 'Learn Vue' },

      { text: 'Build something awesome' }

    ]

  }

})

Trong bảng điều khiển, hãy nhập app4.todos.push({ text: ‘New item’ }). Bạn sẽ thấy một mục mới được thêm vào danh sách.

Xử lý đầu vào của người dùng

Để cho phép người dùng tương tác với ứng dụng của bạn, chúng tôi có thể sử dụng lệnh v-onnày để đính kèm trình xử lý sự kiện gọi các phương thức trên các phiên bản Vue của chúng tôi:

<div id="app-5">

  <p>{{ message }}</p>

  <button v-on:click="reverseMessage">Reverse Message</button>

</div>

var app5 = new Vue({

  el: '#app-5',

  data: {

    message: 'Hello Vue.js!'

  },

  methods: {

    reverseMessage: function () {

      this.message = this.message.split('').reverse().join('')

    }

  }

})

Lưu ý rằng trong phương pháp này, chúng tôi cập nhật trạng thái của ứng dụng mà không cần chạm vào DOM – tất cả các thao tác DOM đều do Vue xử lý và mã bạn viết tập trung vào logic cơ bản.

Vue cũng cung cấp v-modelchỉ thị giúp cho việc ràng buộc hai chiều giữa đầu vào biểu mẫu và trạng thái ứng dụng trở nên dễ dàng:

<div id="app-6">

  <p>{{ message }}</p>

  <input v-model="message">

</div>

var app6 = new Vue({

  el: '#app-6',

  data: {

    message: 'Hello Vue!'

  }

})

Sáng tác với các thành phần

Hệ thống thành phần là một khái niệm quan trọng khác trong Vue, bởi vì nó là một sự trừu tượng cho phép chúng ta xây dựng các ứng dụng quy mô lớn bao gồm các thành phần nhỏ, khép kín và thường có thể tái sử dụng. Nếu chúng ta nghĩ về nó, hầu hết mọi loại giao diện ứng dụng đều có thể được trừu tượng hóa thành một cây các thành phần:

Vue.js là gì?
giới thiệu vue.js là gì

Trong Vue, một thành phần về cơ bản là một thể hiện Vue với các tùy chọn được xác định trước. Đăng ký một thành phần trong Vue rất đơn giản:

// Define a new component called todo-item

Vue.component('todo-item', {

  template: '<li>This is a todo</li>'

})

var app = new Vue(...)

Bây giờ bạn có thể soạn nó trong mẫu của một thành phần khác:

<ol>

  <!-- Create an instance of the todo-item component -->

  <todo-item></todo-item>

</ol>

Nhưng điều này sẽ hiển thị cùng một văn bản cho mọi việc làm, điều này không quá thú vị. Chúng ta có thể chuyển dữ liệu từ phạm vi cha vào các thành phần con. Chúng ta hãy sửa đổi định nghĩa thành phần để làm cho nó chấp nhận một prop :

Vue.component('todo-item', {

  // The todo-item component now accepts a

  // "prop", which is like a custom attribute.

  // This prop is called todo.

  props: ['todo'],

  template: '<li>{{ todo.text }}</li>'

})

Bây giờ chúng ta có thể chuyển việc cần làm vào từng thành phần lặp lại bằng cách sử dụng v-bind:

<div id="app-7">

  <ol>

    <!--

      Now we provide each todo-item with the todo object

      it's representing, so that its content can be dynamic.

      We also need to provide each component with a "key",

      which will be explained later.

    -->

    <todo-item

      v-for="item in groceryList"

      v-bind:todo="item"

      v-bind:key="item.id"

    ></todo-item>

  </ol>

</div>

Vue.component('todo-item', {

  props: ['todo'],

  template: '<li>{{ todo.text }}</li>'

})

var app7 = new Vue({

  el: '#app-7',

  data: {

    groceryList: [

      { id: 0, text: 'Vegetables' },

      { id: 1, text: 'Cheese' },

      { id: 2, text: 'Whatever else humans are supposed to eat' }

    ]

  }

})

Đây là một ví dụ có sẵn, nhưng chúng tôi đã quản lý để tách ứng dụng của mình thành hai đơn vị nhỏ hơn và phần tử con được tách biệt hợp lý khỏi phần tử gốc thông qua giao diện đạo cụ. Giờ đây, chúng tôi có thể cải thiện hơn nữa <todo-item>thành phần của mình với mẫu và logic phức tạp hơn mà không ảnh hưởng đến ứng dụng mẹ.

Trong một ứng dụng lớn, cần phải chia toàn bộ ứng dụng thành các thành phần để giúp cho việc phát triển có thể quản lý được. Chúng ta sẽ nói nhiều hơn về các thành phần ở phần sau trong hướng dẫn , nhưng đây là một ví dụ (tưởng tượng) về mẫu của ứng dụng có thể trông như thế nào với các thành phần:

<div id="app">

  <app-nav></app-nav>

  <app-view>

    <app-sidebar></app-sidebar>

    <app-content></app-content>

  </app-view>

</div>

Liên quan đến các yếu tố tùy chỉnh

Bạn có thể nhận thấy rằng các thành phần Vue rất giống với Thành phần tùy chỉnh , là một phần của Thông số thành phần web . Đó là bởi vì cú pháp thành phần của Vue được mô hình hóa lỏng lẻo theo thông số kỹ thuật. Ví dụ: các thành phần Vue triển khai API Slot và isthuộc tính đặc biệt. Tuy nhiên, có một số điểm khác biệt chính:

Thông số Cấu phần Web đã được hoàn thiện, nhưng không được triển khai nguyên bản trong mọi trình duyệt. Safari 10.1+, Chrome 54+ và Firefox 63+ tự nhiên hỗ trợ các thành phần web. Trong khi đó, các thành phần Vue không yêu cầu bất kỳ polyfills nào và hoạt động nhất quán trong tất cả các trình duyệt được hỗ trợ (IE9 trở lên). Khi cần, các thành phần Vue cũng có thể được bao bọc bên trong một phần tử tùy chỉnh gốc.

Các thành phần Vue cung cấp các tính năng quan trọng không có sẵn trong các phần tử tùy chỉnh thuần túy, đáng chú ý nhất là luồng dữ liệu nhiều thành phần, giao tiếp sự kiện tùy chỉnh và tích hợp công cụ xây dựng.

Mặc dù Vue không sử dụng các yếu tố tùy chỉnh trong nội bộ, nhưng nó có khả năng tương tác tuyệt vời khi nói đến việc sử dụng hoặc phân phối dưới dạng các yếu tố tùy chỉnh. Vue CLI cũng hỗ trợ xây dựng các thành phần Vue tự đăng ký như các phần tử tùy chỉnh gốc.

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

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

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

Liệu thực sự Linq có nhanh hơn vòng lặp for, foreach, while

Liệu thực sự Linq có nhanh hơn vòng lặp for,foreach, while

Bài viết được sự cho phép của tác giả Phạm Công Sơn

Bài viết trước tôi có nêu vấn đề so sánh giữa 2 mảng mà không sử dụng vòng lặp và thay vào đó là sử dụng Linq. Và nhiều bạn cũng đã hỏi vậy tốc độ xử lý giữa dùng vòng lặp và Linq thì dùng cái nào nhanh hơn.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  3 hướng dẫn để bắt đầu kinh doanh trong lĩnh vực nhân sự

Thực ra vấn đề so sánh tốc độ giữa Linq và vòng lặp không còn là chủ đề mới. Các bạn có thể search trên google là ra cả đống.

Liệu thực sự Linq có nhanh hơn vòng lặp for,foreach, while

Có thể thấy là có nhiều kết quả trên google cho vấn đề này.

Tuy nhiên thực sự nhiều câu trả lời cũng chưa thỏa đáng. Chính vì vậy tôi đã làm bài viết này với những kiểm chứng và chính các bạn cũng có thể tự trải nghiệm được.

Nếu như chỉ thực hiện vòng lặp một cách thuần túy. Tôi cam đoan rằng vòng lặp forforeach chắc chắn là nhanh hơn Linq. Và đây là ví dụ minh chứng.

1. Kiểm nghiệm tính tổng số của một mảng
Thực hiện so sánh
Phương thức Kết quả tính tổng Thời gian thực hiện (ticks)
Sử dụng vòng lặp for
Sử dụng vòng lặp foreach
Sử dụng lệnh Join của Linq
Đây là code mà tôi thực hiện kiểm chứng
private long OnStopWatch(Action action)
{
var st = new Stopwatch();
st.Start();
action();
st.Stop();
return st.ElapsedTicks;
}

private void CreateListRandom(int totalNumber, List list1)
{
for (var i = 1; i <= totalNumber; i++)
{
list1.Add(Singleton.Inst.Next(0, 100));
}
}

public void Test1(int totalNumber)
{
if (totalNumber > 50000) throw new Exception("Vui lòng chọn số lượng mảng nhỏ hơn 50000");

var list = new List { };
CreateListRandom(totalNumber, list);

var sumByFor = 0;
var t1 = OnStopWatch(() =>
{
for (var i = 0; i < list.Count; i++) { sumByFor += list[i]; } }); var sumByForEach = 0; var t2 = OnStopWatch(() =>
{
foreach (var item1 in list)
{
sumByForEach += item1;
}
});

var sumByJoinLinq = 0;
var t3 = OnStopWatch(() =>
{
sumByJoinLinq = list.Sum(item => item);
});

this.SetData("Result", new { t1, sumByFor, t2, sumByForEach, t3, sumByJoinLinq, list1 = list.JoinString(item => item, " ") });
}

Rõ ràng với vòng lặp đơn thuần thì for nhanh nhất, Linq là chậm nhất

Nhưng đấy là chúng ta mới chỉ thực hiện với một vòng lặp đơn thuần. Trong thực tế khi duyệt phần tử ta có thể phải sử dụng forforeachwhile lồng nhau thì sao? Ví dụ như sắp xếp hoặc như trong bài trước của tôi là đối sánh giữa 2 phần tử của mảng thì sẽ như thế nào

Dưới đây là kiểm chứng mà tôi tìm ra những phần tử có chung ở 2 mảng rồi thực hiện tính tổng các phần tử này.
2. Kiểm nghiệm tính tổng số phần tử chung giữa 2 mảng
Thực hiện so sánh
Phương thức Kết quả tính tổng Thời gian thực hiện (ticks)
Sử dụng vòng lặp for
Sử dụng vòng lặp foreach
Sử dụng lệnh Join của Linq

Các bạn có thể thấy điều gì không. Thực tế nếu dùng Linq lại cho thấy tốc độ nhanh hơn rất nhiều.

Dưới đây là code tôi thực hiện kiểm chứng
private void CreateListRandom(int totalNumber, List list1, List list2)
{
for (var i = 1; i <= totalNumber; i++)
{
list1.Add(Singleton.Inst.Next(0, 100));
list2.Add(Singleton.Inst.Next(0, 100));
}
}

public void Test2(int totalNumber)
{
if (totalNumber > 50000) throw new Exception("Vui lòng chọn số lượng mảng nhỏ hơn 50000");

// Tạo 2 mảng ngẫu nhiên
var list1 = new List { };
var list2 = new List { };
CreateListRandom(totalNumber, list1, list2);

var sumByFor = 0;
var t1 = OnStopWatch(() =>
{
for(var i = 0; i < list1.Count;i++)
{
var item1 = list1[i];
for(var j = 0; j < list2.Count;j++) { var item2 = list2[j]; if (item1 == item2) sumByFor += item1; } } }); var sumByForEach = 0; var t2 = OnStopWatch(() =>
{
foreach(var item1 in list1)
{
foreach(var item2 in list2)
{
if (item1 == item2)
sumByForEach += item1;
}
}
});

var sumByJoinLinq = 0;
var t3 = OnStopWatch(() =>
{
list1.Join(list2, item1 => item1, item2 => item2, (item1, item2) => sumByJoinLinq += item1).Count();
});

this.SetData("Result", new { t1, sumByFor, t2, sumByForEach, t3, sumByJoinLinq, list1 = list1.JoinString(item => item, " "), list2 = list2.JoinString(item => item, " ") });
}

Tôi cũng đã tìm tới Source code của thư viện Enumerable.cs của Microsoft để tìm hiểu nội dung hàm Join

public static IEnumerable Join<TOuter, TInner, TKey, TResult>(this IEnumerable outer, IEnumerable inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
{
if (outer == null) throw Error.ArgumentNull("outer");
if (inner == null) throw Error.ArgumentNull("inner");
if (outerKeySelector == null) throw Error.ArgumentNull("outerKeySelector");
if (innerKeySelector == null) throw Error.ArgumentNull("innerKeySelector");
if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
return JoinIterator<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
}

static IEnumerable JoinIterator<TOuter, TInner, TKey, TResult>(IEnumerable outer, IEnumerable inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer comparer)
{
Lookup<TKey, TInner> lookup = Lookup<TKey, TInner>.CreateForJoin(inner, innerKeySelector, comparer);
foreach (TOuter item in outer)
{
Lookup<TKey, TInner>.Grouping g = lookup.GetGrouping(outerKeySelector(item), false);
if (g != null)
{
for (int i = 0; i < g.count; i++)
{
yield return resultSelector(item, g.elements[i]);
}
}
}
}

internal static Lookup<TKey, TElement> CreateForJoin(IEnumerable source, Func<TElement, TKey> keySelector, IEqualityComparer comparer)
{
Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
foreach (TElement item in source)
{
TKey key = keySelector(item);
if (key != null) lookup.GetGrouping(key, true).Add(item);
}
return lookup;
}

internal Grouping GetGrouping(TKey key, bool create)
{
int hashCode = InternalGetHashCode(key);
for (Grouping g = groupings[hashCode % groupings.Length]; g != null; g = g.hashNext)
if (g.hashCode == hashCode && comparer.Equals(g.key, key)) return g;
if (create)
{
if (count == groupings.Length) Resize();
int index = hashCode % groupings.Length;
Grouping g = new Grouping();
g.key = key;
g.hashCode = hashCode;
g.elements = new TElement[1];
g.hashNext = groupings[index];
groupings[index] = g;
if (lastGrouping == null)
{
g.next = g;
}
else
{
g.next = lastGrouping.next;
lastGrouping.next = g;
}
lastGrouping = g;
count++;
return g;
}
return null;
}

Đù. Code nó nhiều foreachfor vãi cả đ* mà méo hiểu sao nó nhanh thế nhỉ. Có lẽ có vấn đề gì đó. Hoặc có một thuật toán nào đó mà mình cũng chưa tìm hiểu tới. Nhưng phần nào cũng trả lời cho mọi người thấy là dùng Linq đúng chỗ sẽ tạo hiệu quả rất đáng ngạc nhiên. Và việc tôi dùng Linq để đối sánh giữa 2 mảng cũng rất là hợp lý. Hiện tại trong code mình cũng đã chuyển dần hết sang sử dụng Linq. Tuy nhiên cũng ko phải hoàn toàn. Trường hợp cần sử dụng for thì vẫn phải sử dụng.

Nếu bạn có ý kiến gì hay lý giải được tai sao một số trường hợp như dùng Join lại nhanh hơn for thì hãy chia sẻ để cùng trao đổi. Chúc cuối tuần vui vẻ

Sơn 20

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

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

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

Hướng dẫn cài đặt Flutter

Hướng dẫn cài đặt Flutter

Bài viết được sự cho phép của tác giả Khiêm Lê

Flutter là gì?

Flutter là bộ công cụ UI của Google dùng để xây dựng các ứng dụng đẹp, được biên dịch nguyên bản cho các thiết bị di động, web và máy tính để bàn từ một mã cơ sở duy nhất.

Với Flutter, bạn có thể xây dựng một ứng dụng đẹp, tính tùy biến cực cao, hiệu năng mượt mà. Đặc biệt, với tính năng Hot reload, bạn có thể xem được sự thay đổi chỉ trong vài mili giây.

Một điểm mình đánh giá khá cao nữa là Flutter hỗ trợ debug giao diện cực kì tốt. Bạn có thể chọn từng Widget để xem nó ở dòng code nào, hiện các lưới để canh chỉnh giao diện cho phù hợp…

Với những ưu điểm như vậy, còn chần chừ dì nữa mà không học ngay Flutter nào. Hãy cùng bắt đầu với việc cài đặt Flutter.

Tuyển dụng lập trình Flutter lương cao tại TopDev

Cài đặt Flutter cho Windows

Đầu tiên, bạn truy cập vào flutter.dev, chọn Get started. Sau đó chọn hệ điều hành mà bạn đang sử dụng. Ở đây do mình không có điều kiện nên mình chỉ có thể hướng dẫn các bạn cài đặt trên Windows thôi. Nên mình sẽ chọn Windows.

Yêu cầu hệ thống

Để cài đặt Flutter thì máy tính của bạn cần đáp ứng những yêu cầu sau đây:

  • Windows 7 SP1 hoặc mới hơn (64-bit).
  • Dung lượng trống 400MB (không bao gồm dung lượng cho phần IDE/tools).
  • Các công cụ: Flutter phụ thuộc vào các công cụ có sẵn trong máy tính của bạn:
    • PowerShell 5.0 hoặc mới hơn (cái này đã được tích hợp sẵn vào Windows 10).
    • Git cho Windows 2.x, với tùy chọn chạy câu lệnh git từ cửa sổ lệnh Windows Command Prompt. (Nếu Git đã được cài, hãy chắc chắn rằng bạn có thể chạy câu lệnh git từ cửa sổ lệnh Windows Command Prompt).

Tiến hành cài đặt

Bạn duyệt tìm đến phần Get the Flutter SDK, bấm vào flutter_windows_vxxxx-stable.zip (với xxxx là phiên bản flutter, ví dụ tại thời điểm mình viết Blog này là flutter_windows_v1.9.1+hotfix.6-stable.zip) để tải flutter SDK về. Bạn có thể lưu ở đâu tùy thích sau khi giải nén mình có thể di chuyển nó sau.

Sau khi tải về xong, các bạn giải nén file vừa tải về (tùy chọn Extract here) ta sẽ được một thư mục tên là flutter. Các bạn hãy để thư mục này vào một nơi nào đó mà bạn muốn (lưu ý không được đặt vào thư mục “C:\Program Files\” vì nó yêu cầu quyền riêng tư). Ví dụ mình sẽ làm y như trong docs của Google là tạo một thư mục mới tên là src đặt trong ổ đĩa “C:\” và copy thư mục flutter vào thư mục “C:\src\”.

Bây giờ bạn đã sẵn sàng để chạy lệnh Flutter Console. Nhưng để có thể chạy lệnh flutter từ Command Prompt, bạn nên cập nhật đường dẫn. Các bước thực hiện như sau:

  1. Click phải chuột vào This PC, chọn Properties
  2. Chọn Advanced system settings (gần phía trên bên trái) trong cửa sổ System.
  3. Chọn Enviroment Variables… trong cửa sổ System Properties.
  4. Trong phần User variables, các bạn tìm Variable là PATH và nhấn Edit, nhấn New và thêm đường dẫn đến thư mục “flutter\bin”. Ví dụ của mình là “C:\src\flutter\bin”. Nếu như bạn không tìm thấy Variable PATH bạn nhấn New và đặt tên Variable là PATH và đường dẫn đến thư mục flutter\bin của bạn.
  5. Nhấn OK để lưu tất cả các thay đổi lại.

Vậy là bạn đã có thể chạy lệnh flutter từ Command Prompt rồi. Giờ hãy check thử xem nào. Mở Command Prompt lên và chạy lệnh “flutter –version”. Nếu như nó hiện lên thông tin Flutter, framwork, dart version… thì bạn đã cài thành công. Tiếp theo, chúng ta sẽ phải cài đặt Plugins cho IDE để code với Flutter.

  Biết chọn gì đây? Flutter, React Native hay Xamarin?
  Chat app đơn giản với Flutter

Cài đặt Plugins Flutter

Google hỗ trợ bạn hai IDE đó là Android Studio và Visual Studio Code. Đương nhiên là bạn vẫn có thể sử dụng các IDE khác, nhưng mình không chắc là có sẵn các Plugin cho bạn dùng, và nếu có thì nó cũng là do cá nhân tự phát triển, không đầy đủ bằng. Vậy nên mình sẽ chỉ hướng dẫn các bạn cài đặt trên Android Studio và Visual Studio Code.

Đổi với Android Studio các bạn làm như sau:

  1. Khởi động Android Studio
  2. Ở màn hình Welcome to Android Studio, mở menu Configure (phía dưới góc phải), chọn Plugins
  3. Ở tab Marketplace, các bạn search “flutter”, bạn nhấn install vào plugin Flutter ngay kết quả đầu tiên. Plugin này yêu cầu các bạn cài đặt thêm một plugin nữa là Dart, các bạn chọn Yes để cho phép cài đặt Dart nữa.
  4. Các bạn RESTART IDE để áp dụng thay đổi

Đối với Visual Studio Code, các bạn làm như sau:

  1. Mở Visual Studio Code
  2. Vào tab Extentions trên thanh sidebar bên trái
  3. Search “flutter”, các bạn nhấn Install plugin đầu tiên của kết quả tìm kiếm. Khác với Android Studio, khi cài plugin Flutter thì plugin Dart cũng sẽ được tự cài theo mà không cần bạn xác nhận.

Vậy là mình đã cài xong plugin và sẵn sàng để code với Flutter rồi. Tiếp theo, hãy tạo một máy ảo Android nào.

Tạo máy ảo Android Studio

Để tạo một máy ảo Android Studio, các bạn làm theo các bước sau:

  1. Khởi động Android Studio
  2. Vào menu Configure và chọn AVD Manager
  3. Chọn Create Virtual Device
  4. Chọn một thiết bị và nhấn Next
  5. Các bạn chọn một image x86 hoặc x86_64 đều được (khuyến khích bản mới nhất – nếu không có sẵn thì bạn nhấn Download và đợi một chút để nó tải image đó) sau đó nhấn Next
  6. Trong phần Graphics, bạn chọn Hardware – GLES 2.0. Bạn có sửa các tùy chọn khác nếu muốn và nhấn Finish để tạo máy ảo.
  7. Nhấn nút ▶ để chạy máy ảo vừa tạo

Vậy là mọi thiết lập đã hoàn tất, hãy cùng tạo một project Flutter hello_world và run thử nào!

Kiểm tra và chấp nhận điều khoản

Đến đây gần như bạn đã hoàn tất, giờ hãy kiểm tra lại lần nữa nào. Bạn mở Command Prompt, gõ lệnh “flutter doctor” và nhấn enter, sau khi câu lệnh chạy xong, bạn kiểm tra xem các mục Flutter, Android toolchain, Android Studio, Connected device có được tích hay chưa, nếu chưa bạn hãy kiểm tra và thực hiện lại các bước ở trên mình đã hướng dẫn nhé.

Nếu như các bạn làm theo những gì mình đã hướng dẫn từ đầu bài viết, bạn chỉ còn một bước là hoàn thành. Ở trong Command Prompt, bạn chạy lệnh “flutter doctor –android-licenses”, sau đó, màn hình cmd sẽ hiện lên một loạt các điều khoản SDK, bạn cứ nhấn “y” và enter để đồng ý hết.

  1. Lưu ý là bước chấp nhận điều khoản rất quan trọng, nếu như bạn không chấp nhận điều khoản SDK, khi bạn build app sẽ bị lỗi ngay và không thể build được.
  2. Tạo và chạy Project Flutter
  3. Bạn chọn một thư mục chứa project của bạn, nhấn chuột phải ở vùng trống và chọn Git bash here, gõ lệnh “flutter create hello_world”, nhấn enter và đợi một lúc để nó tạo project. Sau khi tạo xong thì bạn cd vào trong project vừa tạo bằng lệnh “cd hello_world”, tiếp theo nhập lệnh “flutter run” để chạy project trên máy ảo Android đã tạo trước đó. Lần đầu sẽ khá lâu để nó build và run project nên các bạn kiên nhẫn đợi. Và đây là thành quả!
  4. Flutter hello_world
  5. Tổng kết
  6. Vậy là ở trong bài viết này mình đã hướng dẫn các bạn cài đặt Flutter, cài đặt các plugin cho IDE để code với flutter, cài đặt máy ảo, tạo project và run trên máy ảo Android.
  7. Hy vọng bài viết của mình hữu ích với các bạn. Nếu các bạn thấy hay, hãy share bài viết để mình có động lực làm tiếp nhiều bài viết hay hơn nữa để phục vụ các bạn. Nếu có bất kỳ thắc mắc nào, hãy để lại comment bên dưới bài viết để mình có thể giúp các bạn. Cảm ơn các bạn đã đọc bài viết của mình!
  8. Bài viết gốc được đăng tải tại khiemle.dev
  9. Có thể bạn quan tâm:
  1. Xem thêm Việc làm Developer hấp dẫn trên TopDev

“Ứng dụng trên tay – Rinh ngay iPhone” – Trải nghiệm tìm kiếm việc làm chưa bao giờ thú vị đến thế!

Mới đây, TopDev vừa ra mắt ứng dụng TopDev – Tìm việc IT giúp các lập trình viên tìm kiếm việc làm một cách nhanh chóng và hiệu quả với nhiều tính năng nổi bật và trải nghiệm độc đáo.

Hơn thế nữa, TopDev mang đến chương trình “Ứng dụng trên tay – Rinh ngay iPhone” giúp các tài năng IT vừa tìm được công việc phù hợp, vừa có cơ hội nhận được những phần quà hấp dẫn: 

  • Giải thưởng giá trị nhất: Một chiếc iPhone 12 Pro Max VN/A 128GB;
  • 5 e-Voucher mua sắm trên Lazada trị giá 500.000 VND;
  • Cùng hàng trăm e-voucher tại Highlands Coffee.

Tham gia chương trình chỉ với 2 bước đơn giản:

  • Bước 1: Tải App TopDev: Ứng dụng hiện đã hỗ trợ người dùng trên nền tảng iOS và Android.
  • Bước 2: Đăng nhập qua Google hoặc Github trên App TopDev.

Đến đây, bạn đã hoàn thành các bước để tham gia chương trình. Kết quả sẽ được công bố trên website & fanpage TopDev vào ngày 05/08/2021.

Bạn còn chần chờ gì mà không tham gia và khởi sắc sự nghiệp cùng TopDev?

Tải APP liền tay – Rinh ngay quà xịn!

THAM GIA NGAY

>> Ngoài ra, bạn có thể tìm hiểu thêm các tính năng ứng dụng TopDev tại đây: https://topdev.vn/mobile

—–

Thể lệ & điều kiện chương trình:

    • Đối tượng áp dụng: Tất cả người dùng TopDev và cài đặt Ứng dụng TopDev trên di động.
    • Thời gian áp dụng: 23/06/2021 – 30/07/2021.
    • Áp dụng cho tất cả người dùng đăng nhập thành công trên ứng dụng di động TopDev trong thời gian trên.
    • Giải thưởng được công bố vào ngày 05/08/2021 trên website & fanpage của TopDev thông qua hình thức quay số trúng thưởng ngẫu nhiên (*). Giải thưởng sẽ được TopDev liên hệ trực tiếp tài khoản người dùng trúng thưởng để tiến hành thủ tục trao tặng theo luật quy định. Các khoản thuế, phí (nếu có) phát sinh do việc nhận giải thưởng sẽ do cá nhân nhận thưởng chi trả. Riêng e-voucher Lazada & Highlands Coffee sẽ được TopDev gửi mã qua hình thức email hoặc SMS.
    • Thời gian tối đa để cá nhân trúng thưởng xác nhận sau khi đại diện TopDev liên lạc là 14 (mười bốn) ngày, sau thời gian này BTC sẽ tiến hành bầu chọn cá nhân nhận thưởng mới theo các quy định trước đây.
    • Ứng dụng TopDev phải đảm bảo được cài đặt hợp lệ trên thiết bị di động của người dùng trúng thưởng cho đến thời điểm hoàn thành trao giải thưởng.
    • Email đăng nhập mà người dùng sử dụng sẽ là căn cứ xác định trong quá trình quay số và chọn người thắng giải. Mỗi cá nhân sử dụng nhiều email khác nhau trong trường hợp trúng nhiều hơn một giải sẽ chỉ được chỉ định một giải thưởng duy nhất.
    • Mọi thắc mắc giải đáp liên quan đến chương trình khuyến mại này, xin liên hệ email mobile@topdev.vn hoặc fanpage TopDev.
    • Bằng việc tham gia Chương trình Khuyến mại này, người dùng mặc định chấp thuận tất cả các Thể lệ và Điều Kiện của Chương trình Khuyến mại được liệt kê trên.

Tải ứng dụng TopDev tại đây:

         

“TopDev – Tìm việc IT” – Ứng dụng di động giúp tối ưu hóa cơ hội tìm kiếm việc làm IT dành cho các tài năng công nghệ

Topdev giới thiệu ứng dụng di dộng

TopDev – Tìm việc IT là ứng dụng di động chính thức của trang TopDev.vn dành cho lập trình viên tại Việt Nam. Với TopDev, mỗi lập trình viên có thể tìm kiếm việc làm IT một cách nhanh chóng và hiệu quả trên cả PC & Mobile. Không chỉ dừng lại ở đó, ứng dụng di động TopDev hứa hẹn sẽ mang đến trải nghiệm mới với nhiều tính năng nổi bật và trải nghiệm độc đáo.

1. Dễ dàng tìm kiếm việc làm IT và thông tin các công ty công nghệ

Hơn 1,000 vị trí IT tại Việt Nam được cập nhật mỗi ngày trên ứng dụng dành riêng cho các lập trình viên. Ứng dụng TopDev mang đến công cụ tìm kiếm tối ưu giúp Developer tìm việc IT theo kỹ năng, tech stack, công ty, vị trí hoặc mức lương. Từ đó nắm được đầy đủ thông tin về công ty, dự án & phúc lợi của công việc yêu thích.

2. Gợi ý việc làm IT phù hợp với kĩ năng của bạn

Rút ngắn chặng đường tìm kiếm công việc mơ ước, ứng dụng TopDev cung cấp cho người dùng những vị trí việc làm IT mới nhất, tương ứng với kỹ năng, sở trường của họ. Đặc biệt với thao tác vuốt trái hoặc phải, bạn có thể nhanh chóng lựa chọn công việc IT thích hợp, nâng cao cơ hội tìm được công việc theo ý muốn.

3. Ứng tuyển dễ dàng và nhanh chóng

Ứng tuyển một vị trí phù hợp chưa bao giờ đơn giản đến thế. Chỉ với thao tác Upload CV hoặc chọn CV từ danh sách CV sẵn có, bạn đã có thể ứng tuyển dễ dàng vào vị trí ưng ý. CV được đồng bộ ở mọi thiết bị, giúp bạn thuận tiện hơn trong những lần ứng tuyển tiếp theo.

4. Quản lý CV và lịch sử ứng tuyển

Tính năng “Đang tìm việc” và “Auto-apply” giúp hồ sơ của bạn luôn có thể tiếp cận bởi các nhà tuyển dụng tiềm năng. Ngoài ra, bạn có thể chủ động quản lý lịch sử, hồ sơ ứng tuyển cũng như lưu lại công việc & công ty yêu thích để theo dõi và ứng tuyển sau này. Thêm vào đó, tính năng Tạo thông báo công việc mới dựa trên kỹ năng và tech stack sẽ giúp bạn nhanh chóng cập nhật thông tin việc làm với trên thị trường.

5. Tech Blog & Công cụ cho Developer

Với Menu Blog tại ứng dụng TopDev, bạn có thể cập nhật các kiến thức lập trình hữu ích mọi lúc, mọi nơi. Ngoài ra, TopDev còn có thêm công cụ chuyển đổi mức lương  Gross – Net, mang đến sự tiện ích cho các ứng viên IT khi tìm hiểu mức lương cho công việc sắp tới.

Tất cả mọi tiện ích và cơ hội chạm tay sự nghiệp mơ ước nay đã được gói gọn trong chiếc điện thoại của bạn. Cài đặt ứng dụng TopDev – Tìm việc IT ngay hôm nay để khám phá thị trường việc làm IT tại Việt Nam và sẵn sàng khởi sắc sự nghiệp của bạn!

Tải ngay ứng dụng tại đây:

       

Duy nhất từ ngày 23/06 đến hết ngày 30/07/2021, khi ứng tuyển thành công bất kỳ công việc nào trên Ứng dụng di động TopDev, bạn sở hữu ngay cơ hội trúng thưởng phần quà đặc biệt bao gồm: 01 iPhone 12 Pro Max 128GB, 05 e-Voucher Lazada 500.000VND & 100 e-Voucher Highlands Coffee 50.000VND. Tìm hiểu thêm tại đây.

Về TopDev:

TopDev là nền tảng tuyển dụng IT hàng đầu tại Việt Nam sở hữu hơn 300.000 hồ sơ của các lập trình viên và là đơn vị dẫn đầu và duy nhất trong lĩnh vực CNTT tại Việt Nam xây dựng và phát triển thương hiệu nhà tuyển dụng cho hàng trăm doanh nghiệp trong nước và quốc tế.

Ngoài ra, TopDev còn là đơn vị uy tín thực hiện khảo sát, phân tích và phát hành báo cáo thường niên về thị trường IT và nguồn nhân lực IT tại Việt Nam và là nhà tổ chức của 2 sự kiện công nghệ lớn nhất Việt Nam: Vietnam Mobile Day và Vietnam Web Summit.

Architectural Styles vs. Architectural Patterns vs. Design Patterns

ARCHITECTURAL STYLES VS. ARCHITECTURAL PATTERNS VS. DESIGN PATTERNS

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

Trong bài này, hãy cùng định nghĩa và phân biệt một chút giữa 3 khái niệm Architectural Styles vs. Architectural Patterns vs. Design Patterns. Design Patterns chúng ta chắc chắn đã nghe và làm việc nhiều với nó như Singleton, Observer, Factory patterns, vậy còn Architectural Styles vs. Architectural Patterns? Ta thường nên nói là mẫu thiết kế MVC hay là kiến trúc MVC, đọc tiếp sẽ rõ.

Có rất nhiều cách định nghĩa và sử dụng hai cụm từ Architectural Styles và Architectural Patterns trong thế giới phần mềm. Theo MSDN nói thì Architectural Styles và Architectural Patterns là một, nhưng tôi lại thích cách giải thích của George Fairbanks and Michael Keeling và Wikipedia chỉ ra rằng chúng hoàn toàn khác nhau, điểm khác nhau mấu chốt nằm ở phạm vi (scope) của chúng.

Cũng phải nói thêm là Architectural Styles và Architectural Patterns tuy khác nhau nhưng không loại trừ lẫn nhau mà bổ sung cho nhau, như thường lệ, chúng ta cần phải nắm rõ và sử dụng chúng khi cần thiết.

  Clean Architecture: Đứng trên vai những gã khổng lồ
  Con muốn trở thành một Software Architect

ARCHITECTURAL STYLES

Là đỉnh cao nhất khi nói về architecture, cực kỳ high level, có thể chỉ là những nét vẽ sơ khai tạo hình nên bản thiết kế quy định cụ thể các lớp, mô đun cấp cao của ứng dụng và cách các mô đun và lớp tương tác với nhau như thế nào, mối quan hệ giữa chúng.

Architectural styles tell us, in very broad strokes, how to organise our code. It’s the highest level of granularity and it specifies layers, high-level modules of the application and how those modules and layers interact with each other, the relations between them.

Định nghĩa thì luôn mơ hồ, nhất với dân không chuyên về học thuật, vì vậy hãy dùng một số ví dụ về Architectural Styles:

  • Component-based
  • Monolithic application
  • Layered
  • Pipes and filters
  • Event-driven
  • Publish-subscribe
  • Plug-ins
  • Client-server
  • Service-oriented

Lấy ví dụ về Service-oriented (hướng dịch vụ), khi nhìn thấy cụm từ Service-oriented, chúng ta có thể hình dung ra hình hài đầu tiên của system là phải chia nhỏ ra thành các service độc lập với nhau, mỗi service lại được xây dựng và thực thi theo một cách riêng biệt và cuối cùng ghép nối chúng lại (dùng rất nhiều architecture pattern và design pattern) để tạo nên một system hoàn chỉnh. Nó không hề đề cập đến việc có sử dụng MVC, Singleton,… hay không, cho nên ta nói Architectural Style chỉ là khái niệm định hình nên “phong cách” của system sẽ được xây dựng.

ARCHITECTURAL PATTERNS

Một pattern là một giải pháp ứng với một vấn đề lặp đi lặp lại. Trong trường hợp của Architectural Patterns, nó giải quyết các vấn đề liên quan đến Architectural Styles. Ví dụ: “Chúng ta sẽ cần những lớp nào và chúng sẽ tương tác như thế nào, để xây dựng một hệ thống với một tập các layer cụ thể” hoặc “những high-level module nào sẽ có trong Service-Oriented Architecture của chúng ta và cách chúng giao tiếp” , hoặc “sẽ có bao nhiêu tiers trong kiến trúc Client-Server của chúng ta”.

A pattern is a recurring solution to a recurring problem. In the case of Architectural Patterns, they solve the problems related to the Architectural Style. For example, “what classes will we have and how will they interact, in order to implement a system with a specific set of layers“, or “what high-level modules will have in our Service-Oriented Architecture and how will they communicate“, or “how many tiers will our Client-server Architecture have“.

Các Architectural Patterns có ảnh hưởng rộng lớn đến code base, thường ảnh hưởng đến toàn bộ ứng dụng theo chiều ngang (horizontal) (ví dụ: làm thế nào để cấu trúc mã bên trong một layer) hoặc theo chiều dọc (vertical) (ví dụ: một request được xử lý từ những layers bên ngoài vào những layers bên trong và ngược trở lại).

Đọc thêm về Vertical vs Horizontal Approaches

Một vài ví dụ về Architectural Patterns:

  • Three-tier
  • Microkernel
  • Model-View-Controller
  • Model-View-ViewModel

Như vậy khi nói đến mô hình 3-tiers, MVC, MVVM thì ta xếp chúng chung vào một mục: Architectural Patterns. Ví dụ khi ta nói system sẽ được xây dựng theo “phong cách” Client-server, thì tiếp theo ta sẽ quyết định là nên xây dựng theo mô hình 3-tiers, với tier 1 là Client, tier 2 là Server xử lý business logic, tier 3 được tối ưu cho lưu trữ DB. Ta lại áp dụng thê MVVM để phân tách giữa front-end (HTML, Java Swing) với back-end code (model) thông qua view-model (presentation).

DESIGN PATTERNS

Design Patterns khác Architectural Patterns ở phạm vi (scope) của chúng. Design Patterns giải quyết các vấn đề cục bộ, nhỏ lẻ hơn, nó không ảnh hưởng lớn đến code base mà chỉ là 1 phần nhỏ trong đó. Ví dụ: Làm thể nào để khởi tạo 1 object khi chỉ có thể biết được loại object ta muốn khởi tạo lúc run-time (dùng Factory class?) Làm sao để khởi tạo duy nhất 1 object có thể sử dụng trong toàn bộ ứng dụng, ví dụ như Logger, ConfigHoler (Singleton?) Strategy, State machine, ….

Khi nói Plug-ins architecture, chúng ta vẫn chưa có dòng code nào, chỉ có các mô hình làm thế nào để plug&play 1 plugin vô system. Khi nói Model-View-Controller, ta cũng chỉ mới hình dung ra là cần phải có các Model, Controller, View chứ cũng chưa code code. Còn khi nói đến Singleton, là ta biết cần phải tạo ra 1 class với: private constructor, static getInstance() method, …

KẾT LUẬN

Như đã nói từ đầu, tất cả khác nhau nằm ở scope. Architectural Style là bản (phong cách, ý tưởng) thiết kế sơ khởi cho toàn bộ system ở mức độ high-level nhất. Architectural Pattern là tập các bản mẫu, practice để hiện thực Architectural Style; Design Pattern liên quan chặt chẽ tới code, dùng để giải quyết các vấn đề cục bộ khi lập trình.Và tất cả chúng đều được sử dụng trong quá trình phát triển phần mềm, và tất cả phụ thuộc vào thời điểm, mục đích, và người sử dụng.

Đây là bài viết trong loạt bài viết về “Tổng quan về sự phát triển của kiến trúc phần mềm“. Đây là loạt bài viết chủ yếu giới thiệu về một số mô hình kiến trúc phần mềm hay nói đúng hơn là sự phát triển của chúng qua từng giai đoạn, qua đó giúp chúng ta có cái nhìn tổng quát, up-to-date và là roadmap để bắt đầu hành trình chinh phục (đào sâu) thế giới của những bản thiết kế với vai trò là những kỹ sư và kiến trúc sư phần mềm đam mê với nghề.

Bài viết được tham khảo từ:

Architectural Styles vs. Architectural Patterns vs. Design Patterns

Tổng hợp bởi edwardthienhoang

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

Hibernate Logging

Hibernate Logging

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

Với Hibernate chúng ta có thể giao tiếp với cơ sở dữ liệu một cách nhanh chóng. Nhưng, vấn đề có thể làm cho việc debug các lỗi liên quan đến cơ sở dữ liệu trở nên khó khăn. Do đó, chúng ta cần công cụ có thể hữu ích để xem sự tương tác của Hibernate với cơ sở dữ liệu. Ví dụ: SQL được tạo bởi Hibernate để đọc dữ liệu từ một bảng. Để giải quyết vấn đề này, chúng ta cần logging lại SQL đã được tạo và thực thi. Hãy cùng tìm hiểu về Hibernate logging trong bài viết này nhé.

  Hibernate Batch processing
  Hibernate là gì? Sao phải dùng nó thay JDBC?

Cài đặt Log4j2

Có nhiều thư viện hỗ trợ ghi log, trong bài này chúng ta sẽ sử dụng Log4j2, một trong những library fastest về performance và có nhiều advance feature.

Mở file pom.xml và thêm các denpendency sau:

<!-- Log4j2 --> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api --> <dependency>     <groupId>org.apache.logging.log4j</groupId>     <artifactId>log4j-api</artifactId>     <version>2.13.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> <dependency>     <groupId>org.apache.logging.log4j</groupId>     <artifactId>log4j-core</artifactId>     <version>2.13.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --> <dependency>     <groupId>org.hibernate</groupId>     <artifactId>hibernate-core</artifactId>     <version>5.4.7.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency>     <groupId>org.projectlombok</groupId>     <artifactId>lombok</artifactId>     <version>1.18.10</version> </dependency>

Cấu hình Log4j2

Cả 2 Framework Log4j và Logback đều hỗ trợ cấu hình logging sử dụng log4j2.xml file hoặc log4j2.properties. Trong bài này tôi sẽ hướng dẫn các bạn sử dụng log4j2.xml.

Tạo file log4j2.xml trong thư mục resource với nội dung như sau:

<?xml version="1.0" encoding="UTF-8"?> <Configuration>     <Properties>         <Property name="logFolder">logs</Property>     </Properties>     <Appenders>         <!-- Console Appender -->         <Console name="Console" target="SYSTEM_OUT">             <PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n" />         </Console>         <!-- Hibernate File Appender -->         <File name="HibernateFile" fileName="${logFolder}/hibernate.log">             <PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n" />         </File>         <!-- GPCoder File Appender -->         <File name="GPCoderAppFile" fileName="${logFolder}/gpcoderApp.log">             <PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n" />         </File>     </Appenders>     <Loggers>         <!-- Log everything in hibernate -->         <Logger name="org.hibernate" level="info" additivity="false">             <AppenderRef ref="Console" />             <AppenderRef ref="HibernateFile" />         </Logger>         <!-- Log SQL statements -->         <Logger name="org.hibernate.SQL" level="debug" additivity="false">             <AppenderRef ref="Console" />             <AppenderRef ref="HibernateFile" />         </Logger>         <!-- Parameters which are bound to SQL statements (ie. WHERE clause) -->         <Logger name="org.hibernate.type.descriptor.sql" level="trace" additivity="false">             <AppenderRef ref="Console"/>             <AppenderRef ref="HibernateFile" />         </Logger>         <!-- Log GP Coder App statements -->         <Logger name="com.gpcoder" level="debug" additivity="false">             <AppenderRef ref="Console" />             <AppenderRef ref="GPCoderAppFile" />         </Logger>         <Root level="error">             <AppenderRef ref="Console" />             <AppenderRef ref="File" />         </Root>     </Loggers> </Configuration>

Ý nghĩa các tham số cấu hình log4j, các bạn xem lại bài viết “Giới thiệu Java logging“.

Trong cấu hình trên, tôi tạo 2 logger:

  • Tất cả các log từ org.hibernate (bao gồm SQL, descriptor SQL paramter) sẽ lưu trong file logs/hibernate.log và show ở console.
  • Tất cả các log từ com.gpcoder sẽ lưu trong file logs/gpcoderApp.log và show ở console.

Các category của Hibernate Logger chúng ta có thể cấu hình:

  • org.hibernate : bao gồm tất cả các log message của Hibernate. Hãy cẩn thận log này trong môi trường production, bởi vì một số lượng message sẽ được log.
  • org.hibernate.SQL : câu lệnh SQL được Hibernate generate và gởi đến JDBC, chẳng hạn INSERT INTO
  • org.hibernate.type.descriptor.sql : Các parameter của câu lệnh SQL, chẳng hạn WHERE id = ? . Thường kết hợp với org.hibernate.SQL để có được thông tin SQL đầy đủ.
  • org.hibernate.stat : Lưu các thống kê (statistic) hoạt động của Hibernate Session.
  • org.hibernate.tool.hbm2ddl : Lưu câu lệnh DDL, chẳng hạn CREATE TABLE.
  • org.hibernate.cache : Thông tin về các hoạt động Hibernate second-level cache.
  • org.hibernate.pretty : ghi lại trạng thái tại thời điểm flush tối đa 20 Entity cho loại log này.
  • org.hibernate.hql.internal.ast.AST : Nhóm các HQL và SQL AST trong quá trình phân tích cú pháp truy vấn.

Mở file hibernate.cfg.xml:

  • hibernate.show_sql=false : do đã cấu hình logger cho Hibernate SQL.
  • hibernate.generate_statistics=true : hiển thị thống kê hoạt động của Hibernate Session.
<hibernate-configuration>     <session-factory>         <!-- Database setting -->         <!-- Hide SQL -->         <property name="show_sql">false</property>         <!-- Show Session Metrics -->         <property name="generate_statistics">true</property>              </session-factory> </hibernate-configuration>

Ví dụ sử dụng Log4j2

package com.gpcoder; import com.gpcoder.entities.Category; import com.gpcoder.utils.HibernateUtils; import lombok.extern.log4j.Log4j2; import org.hibernate.Session; import org.hibernate.SessionFactory; @Log4j2 public class HibernateExample {     public static void main(String[] args) {         try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();              Session session = sessionFactory.openSession();) {             session.beginTransaction();             Category cat = new Category();             cat.setName("Hibernate Logging");             log.debug("Insert new category: " + cat);             session.save(cat);             session.getTransaction().commit();         }     } }

Console output:

2020-Apr-01 21:49:39 PM [main] DEBUG com.gpcoder.HibernateExample - Insert new category: Category(id=null, name=Hibernate Logging, posts=null) 2020-Apr-01 21:49:39 PM [main] DEBUG org.hibernate.SQL - insert into Category (name) values (?) 2020-Apr-01 21:49:39 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [Hibernate Logging] 2020-Apr-01 21:49:39 PM [main] INFO  org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {     513515 nanoseconds spent acquiring 1 JDBC connections;     306945 nanoseconds spent releasing 1 JDBC connections;     12625794 nanoseconds spent preparing 1 JDBC statements;     705225 nanoseconds spent executing 1 JDBC statements;     0 nanoseconds spent executing 0 JDBC batches;     5060781 nanoseconds spent performing 2 L2C puts;     0 nanoseconds spent performing 0 L2C hits;     0 nanoseconds spent performing 0 L2C misses;     5350453 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);     0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections) }

Log file:

hibernate.log

2020-Apr-01 21:49:39 PM [main] DEBUG org.hibernate.SQL - insert into Category (name) values (?) 2020-Apr-01 21:49:39 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [Hibernate Logging] 2020-Apr-01 21:49:39 PM [main] INFO  org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {     513515 nanoseconds spent acquiring 1 JDBC connections;     306945 nanoseconds spent releasing 1 JDBC connections;     12625794 nanoseconds spent preparing 1 JDBC statements;     705225 nanoseconds spent executing 1 JDBC statements;     0 nanoseconds spent executing 0 JDBC batches;     5060781 nanoseconds spent performing 2 L2C puts;     0 nanoseconds spent performing 0 L2C hits;     0 nanoseconds spent performing 0 L2C misses;     5350453 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);     0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections) }

gpcoderApp.log

2020-Apr-01 21:49:39 PM [main] DEBUG com.gpcoder.HibernateExample - Insert new category: Category(id=null, name=Hibernate Logging, posts=null)

Như bạn thấy, log của chúng ta được lưu rất đầy đủ và tách biệt riêng ở 2 file: hibernate.log và gpcoderApp.log.

Better SQL logger with P6Spy

Bằng cách sử dụng P6Spy với Hibernate, chúng ta có thể ghi lại thời gian thực hiện hiện tại, tổng thời gian đã thực hiện, câu lệnh sql với biến liên kết, câu lệnh sql được thực thi, v.v.

Đầu tiên cần thêm thư viện p6spy vào file pom.xml:

<!-- https://mvnrepository.com/artifact/p6spy/p6spy --> <dependency>     <groupId>p6spy</groupId>     <artifactId>p6spy</artifactId>     <version>3.8.7</version> </dependency>

Tiếp theo, chúng ta cần sửa lại 2 thông số kết nối database sau:

hibernate.cfg.xml

<hibernate-configuration>     <session-factory>         <!-- Database setting --> <!--     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>--> <!--     <property name="connection.url">jdbc:mysql://192.168.64.2:3306/gp_system?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf8</property>-->         <property name="connection.driver_class">com.p6spy.engine.spy.P6SpyDriver</property>         <property name="connection.url">jdbc:p6spy:mysql://192.168.64.2:3306/gp_system?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf8</property>     </session-factory> </hibernate-configuration>

Cuối cùng, tạo 1 file có tên spy.properties nằm trong thư mục src/main/resources:

driverlist=com.mysql.cj.jdbc.Driver dateformat=yyyy-MMM-dd HH:mm:ss a #appender=com.p6spy.engine.spy.appender.Slf4JLogger appender=com.p6spy.engine.spy.appender.StdoutLogger #appender=com.p6spy.engine.spy.appender.FileLogger #logfile=C:/spy.log logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat customLogMessageFormat=%(currentTime) | %(executionTime) | %(category) | connection %(connectionId) | %(sqlSingleLine)

Ở đây, do mình muốn test ngay trên console, nên đã sử dụng appender là com.p6spy.engine.spy.appender.StdoutLogger. Nếu các bạn muốn ghi log ra file, có thể dùng appender com.p6spy.engine.spy.appender.FileLogger và chỉ ra đường dẫn của file log trong thuộc tính logfile.

Chi tiết các cấu hình spy.properties các bạn có thể tham khảo thêm ở P6Spy Configuration document.

Chạy lại chương trình trên, chúng ta có output như sau:

2020-Apr-01 21:52:21 PM [main] DEBUG org.hibernate.SQL - insert into Category (name) values (?) 2020-Apr-01 21:52:21 PM [main] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [Hibernate Logging] 2020-Apr-01 21:52:21 PM | 0 | statement | connection 0 | insert into Category (name) values ('Hibernate Logging') 2020-Apr-01 21:52:21 PM | 0 | commit | connection 0 |  2020-Apr-01 21:52:21 PM [main] INFO  org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {     493749 nanoseconds spent acquiring 1 JDBC connections;     266651 nanoseconds spent releasing 1 JDBC connections;     13746392 nanoseconds spent preparing 1 JDBC statements;     1334640 nanoseconds spent executing 1 JDBC statements;     0 nanoseconds spent executing 0 JDBC batches;     4606268 nanoseconds spent performing 2 L2C puts;     0 nanoseconds spent performing 0 L2C hits;     0 nanoseconds spent performing 0 L2C misses;     4929280 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);     0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections) }

Như bạn thấy, P6Spy giúp chúng ta log ra câu SQL đầy đủ với các tham số, thời gian thực thi, … Thư viện này đặc biệt hữu ích khi cần kiểm tra dữ liệu đã lấy chính xác hay chưa với các tham số truyền vào đầy đủ, chúng ta dễ dàng copy và thực thi SQL trực tiếp trong hệ quản trị để kiểm tra tính đúng đắn của SQL. Nhờ vậy dễ dàng debug và phát hiện lỗi dữ liệu hơn.

Bài viết đến đây là hết, hy vọng giúp ích cho các bạn!!!

Tài liệu tham khảo:

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

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

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

Phân biệt các level Developer? Thực tập, Fresher, Junior… có gì khác biệt?

PHÂN BIỆT CÁC LEVEL DEVELOPER? THỰC TẬP, FRESHER, JUNIOR… CÓ GÌ KHÁC BIỆT?

Bài viết được sự cho phép của BQT Kinh nghiệm lập trình

Trong ngành công nghệ, các thuật ngữ về lập trình viên được phân theo hệ thống cấp bậc rõ ràng. Tùy vào từng cấp có sự đánh giá nhất định về trình độ và kinh nghiệm riêng. Và mỗi cấp cũng có mức độ trách nghiệm riêng. Vậy làm thế nào để có thể phân biệt các level Developer? Thực tập, Fresher, Junior… liệu có giống nhau? Hãy cùng tham khảo bài viết sau đây để giải đáp mọi thắc mắc.

Những nấc thang của sự nghiệp lập trình viên

Fresher/Junior Developer

Đây là nấc thang đầu tiên của những bạn sinh viên ngành IT khi mới ra trường. Fresher/Junior Developer không có bề dày kinh nghiệm lâu năm, người ở vị trí này chủ yếu tích lũy tầm 6 tháng – 1 năm kinh nghiệm làm việc chuyên nghiệp thực tế. Cũng vì thế, các công ty khi tuyển dụng bậc thang đầu tiên của sự nghiệp lập trình viên đều tổ chức các khóa training ngắn hạn.

Fresher/Junior Developer đòi hỏi phải có thể viết được các script đơn giản, hiểu được toàn bộ vòng đời của một ứng dụng và phải có hiểu biết sơ bộ về cơ sở dữ liệu cũng như các dịch vụ ứng dụng. Đây là level đầu tiên cũng là bước khởi đầu để bước trên con đường trở thành một lập trình viên chuyên nghiệp. Vì vậy, khi còn là một Fresher/Junior Developer cần cố gắng tích lũy kiến thức, kinh nghiệm để có được nền tảng vững chắc cho các bước tiến sau.

Phân biệt các level Developer? Thực tập, Fresher, Junior... có gì khác biệt?

Cách tốt nhất đơn giản nhất để có thể phân biệt các cấp Developer

Senior Developer

Senior Developer là cấp thứ 2 sau khi đã thực tập và hoàn thành cấp Fresher/Junior Developer. Các lập trình viên ở cấp này phải có ít nhất từ 4 – 10 năm kinh nghiệm trong lĩnh vực công nghệ thông tin. Khi đạt đến level này, bắt buộc các Senior Developer phải viết được những ứng dụng phức tạp, đòi hỏi tư duy logic, sự sáng tạo và kinh nghiệm lập trình cao. Hơn hết, lập trình viên phải am hiểu sâu sắc về vòng đời của một ứng dụng cũng như các cơ sở dữ liệu cũng như các dịch vụ ứng dụng khác. Senior Developer được hiểu là những người thật sự giỏi trong việc tạo lập toàn bộ ứng dụng trên quy mô lớn. Đây cũng là cấp bậc có số lượng lập trình viên nhiều nhất hiện nay. Và đối với những cá nhân không hứng thú với việc quản lý thì đây thật sự là một vị trí rất tuyệt vời.

Tech Lead/ Team Lead

Leader là những người có ít nhất 7 năm kinh nghiệm làm việc với vai trò lập trình viên. Về cơ bản, Leader cũng cần có những kỹ năng tương tự như Senior Developer tuy nhiên cấp này đòi hỏi trình độ cao hơn cũng như tinh thần trách nghiệm mạnh mẽ hơn. Team leader được hiểu như vai trò chuyển tiếp vào chức vị quản lý cấp trung. Còn Tech lead lại đơn thuần là vai trò kỹ thuật, phù hợp với những bạn không phù hợp với việc quản lý. Các lập trình viên ở cấp này thường viết code trên một hệ thống phức tạp hơn, sử dụng kiến thức và kinh nghiệm chủ yếu nghiêng về lập trình patterns và anti-patterns để hoạch định ra kết cấu của một phần mềm thành công.

Phân biệt Fresher và Junior

Nhìn chung, cả 3 thuật ngữ này đều được sử dụng để biểu thị các bạn trẻ chưa có kinh nghiệm làm việc lâu năm trong lĩnh vực công nghệ thông tin. Tuy nhiên, 3  từ này không hoàn toàn trùng khít lên nhau về mặt ý nghĩa, giữa chúng cũng rạch ròi nhiều điểm rất riêng

–   Fresher: đây là cụm từ dùng để chỉ các bạn sinh viên trường công nghệ thông tin vừa mới tốt nghiệp. Đa phần những Fresher đều là người đã được trang bị đầy đủ kiến thức, kỹ năng và đang cần tìm một môi trường phù hợp để ứng dụng, triển khai. Thông thường, các công ty khi nhận nhân viên mới sẽ mở một khóa đào tạo ngắn hạn chế các Fresher có thể quen với công việc của người mới bắt đầu.

Xem thêm các vị trí tuyển dụng Fresher từ các công ty HOT

–   Junior: từ này được dùng để gọi những lập trình viên ở trình độ sơ cấp. Họ không hẳn là thực tập sinh hay những người mới ra trường. Tuổi nghề để xác định Junior là quan trọng nhưng không phải là yếu tố quyết định hàng đầu. Thậm chí vẫn có trường hợp Junior lớn tuổi hơn cả Senior

–   Thực tập: thực tập sinh là những sinh viên năm cuối trường IT hoặc những người đang được nhận làm training cho một đơn vị tổ chức hoặc công ty nào đó

Việc làm IT tại Hồ Chí Minh

Việc làm IT tại Đà Nẵng

Làm thế nào để vững bước trên các nấc thang nghề lập trình viên?

Để có thể vững bước trên con đường lập trình viên và không ngừng chinh phục các nấc thang sự nghiệp cần nuôi dưỡng một niềm đam mê không ngừng nghỉ. Bởi khi xuất phát từ vị trí sơ cấp, có rất nhiều điều mới mẻ cần học hỏi cũng như phải vượt qua rất nhiều áp lực. Sau khi đã chinh phục được level 1, các bạn lập trình viên bắt đầu bước vào môi trường chuyên nghiệp với vốn kiến thức sâu rộng cũng như năng khiếu bẩm sinh. Chính vì vậy, nỗ lực luôn là một trong những điều không nên đánh rơi trên bước đường chinh phục công việc lập trình.

Tùy vào mỗi chức danh quy định các cấp trình độ chuyên ngành công nghệ thông tin khác nhau. Với những chia sẻ trên đây hy vọng quý bạn đọc có thể tích lũy được nhiều điều bổ ích.

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

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

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

Sử dụng Spring Security trong Spring Boot

Sử dụng Spring Security trong Spring Boot

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

Mình đã giới thiệu với các bạn cách cài đặt và cấu hình để sử dụng Spring Security trong các ứng dụng Spring MVC. Với Spring Boot application, thì việc cấu hình Spring Sẹcurity sẽ đơn giản hơn rất nhiều. Chúng ta không cần phải làm từng step để cấu hình cho phần authentication và authorization của ứng dụng. Spring Boot hỗ trợ chúng ta giảm bớt rất nhiều thao tác với những cấu hình mặc định cho Spring Security. Cụ thể như thế nào? Mình sẽ chia sẻ với các bạn một số kiến thức về Spring Security trong Spring Boot application các bạn nhé!

  Bảo mật ứng dụng Java web bởi Spring Security
  Cài đặt Spring Boot CLI

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

Sử dụng Spring Security trong Spring Boot

với Spring Web và Spring Security dependencies như sau:

Kết quả:

Ngay lúc này, các bạn chạy ứng dụng lên rồi request tới địa chỉ http://localhost:8080, các bạn sẽ thấy trang login mặc định của Spring Security được hiển thị như sau:

Rõ ràng là, Spring Boot đã có những cấu hình mặc định cho Spring Security ngay khi chúng ta thêm dependency của nó. Username mặc định để các bạn có thể đăng nhập vào là “user” và password được generate và in ra trong console log đó các bạn.

Sử dụng Spring Security trong Spring Boot

Nhập thông tin username, password rồi nhấn nút Sign In, các bạn sẽ thấy kết quả như sau:

Đây là do chúng ta chưa định nghĩa một request nào trong ứng dụng của chúng ta đó các bạn. Nếu mình định nghĩa controller như sau:

package com.huongdanjava.springboot.springsecurity;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@GetMapping("")
public String sayHello() {
return "Hello";
}

}

thì các bạn sẽ thấy kết quả như sau:

Các bạn có thể thay đổi username và password mặc định này bằng cách cấu hình 2 property sau trong tập tin application.properties:

spring.security.user.name=khanh
spring.security.user.password=123456

Chạy lại ứng dụng, các bạn sẽ thấy default password sẽ không được generate nữa và chúng ta có thể sử dụng username và password mà mình đã khai báo ở trên để đăng nhập.

Spring Boot sử dụng cấu hình mặc định của class WebSecurityConfigurerAdapter để cấu hình cho Spring Security. Nếu take a look vào code của class WebSecurityConfigurerAdapter, các bạn sẽ thấy mặc định thì Spring Security cấu hình cho phần authorization như sau:

protected void configure(HttpSecurity http) throws Exception {
this.logger.debug("Using default configure(HttpSecurity). "
+ "If subclassed this will potentially override subclass configure(HttpSecurity).");
http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
http.formLogin();
http.httpBasic();
}

Như các bạn thấy, mặc định Spring Security sẽ chặn hết tất cả các request, tự động generate login form và sử dụng http basic cho phần authentication. Như mình đã nói với các bạn trong bài viết về Cấu hình Spring Security sử dụng WebSecurityConfigurerAdapter và AbstractSecurityWebApplicationInitializer, chúng ta có thể override class WebSecurityConfigurerAdapter để thay đổi cấu hình này.

package com.huongdanjava.springboot.springsecurity;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
}

và tất nhiên, các bạn cũng có thể override phương thức configure(AuthenticationManagerBuilder auth) để thay thế cho phần cấu hình authentication nha các bạn!

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

6 Điều Cần Tránh Khi Phỏng Vấn Để Tăng Cơ Hội Thành Công

cần tránh khi phỏng vấn
Những Điều Cần Tránh Khi Phỏng Vấn Để Tăng Cơ Hội Thành Công

Quá trình phỏng vấn xin việc luôn có rất nhiều vấn đề đáng nói và cần lưu tâm nếu bạn muốn nó diễn ra hoàn hảo. Với những sinh viên vừa ra trường và đang mong muốn tìm cho mình một “bến đỗ” thì đây càng được xem là cơ hội cần phải đầu tư nhiều thời gian và sức lực hơn cả. Dù đã chuẩn bị rất kỹ càng về chuyên môn và kiến thức cho buổi phỏng vấn nhưng nếu phạm phải những điều cần tránh khi phỏng vấn, có thể sẽ khiến kết quả không được như mong đợi. Vậy đâu là vấn đề cần tránh trong một buổi phỏng vấn? Tìm hiểu thêm với bài viết dưới đây nhé!

cần tránh khi phỏng vấn
Những vấn đề cần lưu ý khi phỏng vấn

1. Đến muộn hoặc quá sớm so với giờ hẹn

Đúng giờ – đây là yếu tố cực kỳ quan trọng mà khi tìm hiểu về những vấn đề nên và không nên của một buổi phỏng vấn thành công bạn chắc chắn đã được nghe qua. Đúng giờ cho thấy bạn là người chuyên nghiệp và tôn trọng thời gian của đối phương. Điều này giúp ứng viên tạo được thiện cảm tốt hơn với nhà tuyển dụng. Thêm vào đó, việc đến trễ chắc chắn sẽ khiến bạn vội vàng và thiếu sự chuẩn bị cho buổi phỏng vấn hơn. Một số người thậm chí còn trở nên lo lắng và mất bình tĩnh dẫn đến quá trình phỏng vấn không còn được suôn sẻ.

Ngược lại, đến quá sớm so với giờ hẹn cũng là điều cần tránh khi phỏng vấn. Thời gian hoàn hảo nhất để xuất hiện là sớm hơn giờ phỏng vấn từ 5 – 15 phút. Vì nếu đến quá sớm, bạn có thể khiến nhà tuyển dụng bối rối vì chưa chuẩn bị xong cho buổi phỏng vấn. Thêm vào đó, khi phải mất quá nhiều thời gian chờ đợi khiến cảm giác hăng hái và sự nhiệt huyết đã chuẩn bị cho phỏng vấn dần biến mất.

  NÊN & KHÔNG NÊN Để Đàm Phán Lương Thành Công Khi Phỏng Vấn
  Cách Viết Summary Trên LinkedIn Để Thu Hút Các Nhà Tuyển Dụng

2. Không tìm hiểu chi tiết thông tin công ty

Trong quá trình phỏng vấn, khi được hỏi về những vấn đề liên quan đến công việc, đây chính là thời điểm thích hợp để bạn tận dụng những thông tin về công ty ứng tuyển đã tìm hiểu được để trả lời. Từ những gì bạn chia sẻ, bạn sẽ được nhà tuyển dụng giới thiệu chuyên sâu hơn về quy trình hoạt động của doanh nghiệp, các vấn đề thực tế sẽ xuất hiện trong quá trình làm việc,… Đây chính là cầu nối giúp hai bên trao đổi thông tin hiệu quả hơn.

Vậy nên trước buổi phỏng vấn hãy dành thời gian để tìm hiểu những thông tin cơ bản về công ty như sứ mệnh, nhiệm vụ, giá trị,… Nếu có thời gian bạn có thể tìm hiểu thêm về cả những sản phẩm mà công ty đã tạo ra và đang lên kế hoạch phát triển trong thời gian tới. Những thông tin này chắc chắn sẽ giúp ích rất nhiều trong quá trình trao đổi với nhà tuyển dụng.

Xem thêm Làm Thế Nào Để Cover Letter Ấn Tượng Hơn Với Những Ứng Viên Chưa Có Kinh Nghiệm?

3. Không có kỹ năng giao tiếp tốt

Kỹ năng giao tiếp cũng là một yếu tố quan trọng được người phỏng vấn rất lưu tâm và đánh giá xuyên suốt trong quá trình trao đổi giữa hai bên. Trong buổi phỏng vấn, hãy cố gắng thể hiện những kỹ năng của mình bằng ngôn ngữ cơ thể, giao tiếp bằng ánh mắt hay bắt tay với người phỏng vấn,…

Đây sẽ là yếu tố được nhà tuyển dụng đánh giá rất cao và tạo sự ấn tượng với họ ngay trước khi buổi phỏng vấn bắt đầu và có được sự thiện cảm trong suốt quá trình phỏng vấn. Lưu ý hãy nhớ tắt chuông điện thoại trước khi vào phỏng vấn để tránh buổi phỏng vấn bị gián đoạn khi có cuộc gọi đến bất ngờ.

lưu ý khi phỏng vấn
Kỹ năng giao tiếp tốt sẽ tạo được thiện cảm trong mắt nhà tuyển dụng

4. Trang phục không phù hợp

Vẻ bề ngoài là yếu tố đầu tiên tác động đến nhà tuyển dụng trước khi buổi phỏng vấn chính thức diễn ra, chính vì thế trang phục thiếu chỉn chu là một trong những vấn đề cần tránh khi phỏng vấn. Hãy chịu khó đầu tư vào trang phục để tạo cảm giác chuyên nghiệp hơn trong mắt người phỏng vấn. Không cần phải quá cầu kì hay quần áo đắt tiền, bạn chỉ cần mặc trang phục lịch sự, gọn gàng và thẳng thớm. Đừng ăn mặc quá tuềnh toàng vì chắc chắn sẽ khiến nhà tuyển dụng cảm thấy không hài lòng, thậm chí là khó chịu và cảm thấy không được tôn trọng.

Bạn có thể lựa chọn các trang phục công sở cơ bản nhất như quần tây hoặc chân váy đi kèm với áo sơ mi. Đây là lựa chọn an toàn nhất vì bạn vẫn chưa biết được văn hóa ăn mặc của công ty như thế nào nên đừng quá phá cách. Với các bạn nữ, không nên trang điểm quá đậm, sử dụng nước hoa có mùi hương quá nồng hoặc mặc những chiếc đầm có thiết kế và màu sắc quá nổi bật.

5. Thể hiện thái độ và câu trả lời quá tiêu cực là điều cần tránh khi phỏng vấn

Vì đây là lần đầu bạn được tiếp xúc và trao đổi trực tiếp với nhà tuyển dụng, vậy nên hãy cho họ thấy nguồn năng lượng tích cực và thái độ lạc quan của bạn đối với các vấn đề được nhắc đến, kể cả với các câu hỏi liên quan đến công ty cũ. Hãy cố gắng giữ thái độ trung lập và hài hòa, đừng nên quá tiêu cực khi trả lời phỏng vấn.

Bên cạnh đó, đừng trả lời câu hỏi một cách quá rập khuôn. Có một số câu hỏi cơ bản mà bất kỳ buổi phỏng vấn nào bạn cũng sẽ được hỏi qua. Đương nhiên việc tìm hiểu những mẹo trả lời giúp ghi điểm với nhà tuyển dụng là rất cần thiết, nhưng bạn chỉ nên tham khảo cách trả lời và linh hoạt thay đổi cho phù hợp với kinh nghiệm và kỹ năng mà mình có được trong quá trình làm việc. Vì nhà tuyển dụng chắc chắn đã phỏng vấn rất nhiều ứng viên khác nhau nên điều họ cần ở bạn là sự khác biệt thay vì câu trả lời giống với những người khác. Hãy thể hiện dấu ấn cá nhân của mình nếu muốn được người phỏng vấn đánh giá cao.

Xem thêm Kỹ Năng Giao Tiếp Trong Tuyển Dụng Và Cách Cải Thiện

6. Đề cập quá nhiều đến vấn đề tiền bạc

Đề cập quá nhiều hoặc nhắc đến vấn đề tiền bạc quá sớm cũng sẽ khiến bạn mất điểm trong mắt nhà tuyển dụng. Đương nhiên lương thưởng là vấn đề quan trọng với mọi ứng viên, tuy nhiên điều nhà tuyển dụng muốn biết ở bạn nhiều hơn vẫn là những kinh nghiệm, khả năng làm việc cũng như mục tiêu nghề nghiệp mà bạn đặt ra với bản thân mình. Sau khi ứng viên đã chia sẻ thành thật các vấn đề và nếu nhà tuyển dụng cảm thấy hài lòng, họ chắc chắn sẽ đề cập đến chuyện lương thưởng với bạn. Đây chính là thời điểm thích hợp để bạn trao đổi về vấn đề này.

Khi đã được nhà tuyển dụng trao đổi đến vấn đề lương thưởng, đây ngược lại không phải lúc để bạn thể hiện sự khiêm nhường của bản thân mà hãy cố gắng làm rõ những khoản lương thưởng của công ty. Các loại phúc lợi và lương làm thêm giờ,… hãy cố gắng trao đổi rõ ràng để được nhà tuyển dụng giải đáp mọi thắc mắc mà bạn đang gặp phải để tránh những khúc mắc về sau.

Đối với những ứng viên chưa có nhiều kinh nghiệm phỏng vấn thực tế, việc mắc phải một số sai lầm khi phỏng vấn là điều hoàn toàn có thể xảy ra. Tuy nhiên tham khảo thêm một số mẹo để biết điều gì nên làm điều gì nên tránh chắc chắn sẽ giúp ích rất nhiều cho một buổi phỏng vấn thuận lợi hơn. Đón đọc thêm nhiều bài viết bổ ích khác cùng TopDev bạn nhé!

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

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

Window IIS PHP: Fix lỗi Curl SSL Certificate Problem

Chào các bạn, bài viết hôm nay mình sẽ chia sẻ 1 cách để fix lỗi Curl SSL khi PHP hoạt động trên Windows Server trên nền IIS.

Bài viết được sự cho phép của BQT Kinh nghiệm lập trình

Chào các bạn, bài viết hôm nay mình sẽ chia sẻ 1 cách để fix lỗi Curl SSL khi PHP hoạt động trên Windows Server trên nền IIS.

  Fix lỗi "Fopen Failed To Open Stream: Permission Denied Windows Server"
  Fix Lỗi "RDP Authentication Error Has Occurred – The Function Requested Is Not Supported"

Lỗi Curl SSL xảy ra khi nào?

Thông thường khi bạn cài đặt PHP trên máy chủ Windows Server, mọi thứ hoạt động bình thường. Cho đến một ngày bạn add thêm SSL Certificate cho ứng dụng của bạn. Có thể bạn sẽ gặp lỗi dưới đây:

“Curl (60) SSL Certificate Problem: Unable to get local issuer certificate”

Window IIS PHP: Fix lỗi Curl SSL Certificate Problem

PHP Curl được sử dụng trong hầu hết các ứng dụng có dùng API

Lỗi này không quá nghiêm trọng, tuy nhiên nếu không biết cách xử lý, bạn sẽ tốn khá nhiều thời gian vào việc này.

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

Fix lỗi Curl SSL Certificate Problem: Unable to get local issuer certificate

Vấn đề này xảy ra do bị thiếu chứng chỉ CA từ Mozilla. Do đó ta chỉ cần thêm chứng chỉ này vào thư mục SSL của PHP.
Các bước thực hiện như sau:

  • Bước 1: Tải “cacert.pem” từ link: http://curl.haxx.se/docs/caextract.html (https://curl.haxx.se/ca/cacert.pem)
  • Bước 2: Lưu file cacert.pem vào folder SSL của PHP. Tùy thuộc vào phiên bản PHP bạn đang sử dụng. Đường dẫn có thể như sau:

  • Bước 3: Thêm đường dẫn vào file cấu hình php.ini của bạn.

  • Bước 4: Khởi động lại IIS Server của bạn. Có thể chạy câu lệnh “iisreset” từ command prompt với quyền admin để khởi động lại IIS server.
  • Cuối cùng test và kiểm tra lại các bước thực hiện trên

Chúc các bạn thành công!

Bài viết gốc được đăng tải tại kinhnghiemlaptrinh.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

Hibernate Cache

Hibernate Cache

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

Một trong những lợi thế của abstraction layer cơ sở dữ liệu sử dụng ORM Framework là khả năng lưu trữ dữ liệu bộ nhớ cache một cách trong suốt từ kho lưu trữ bên dưới. Điều này giúp loại bỏ chi phí truy cập cơ sở dữ liệu cho dữ liệu thường xuyên truy cập. Nhờ vậy mà hiệu suất của ứng dụng tăng. Hiệu suất đạt được có thể là đáng kể nếu tỷ lệ đọc / ghi của nội dung được lưu trong bộ nhớ cache cao, đặc biệt đối với các Entity bao gồm các Entity Graph lớn.

Trong bài này chúng ta sẽ cùng tìm hiểu về Hibernate Cache để improve performance của ứng dụng.

  Hibernate Batch processing
  Hibernate Interceptor & StatementInspector

Cache là gì?

Cache hay bộ nhớ đệm là cơ chế lưu các dữ liệu trong phiên làm việc trước của các ứng dụng, nhằm giúp việc tải data trong các phiên làm việc sau được nhanh hơn.

Lợi ích đến từ cache:

  • Cải thiện tốc độ, các yêu cầu gần như có thể đáp ứng tức thời.
  • Giảm thiểu băng thông, giảm thiểu hoạt động bị lặp lại nhiều lần không cần thiết.
  • Tăng hiệu suất phần cứng, tăng hiệu suất, giảm thiểu các xử lý phải thông qua CPU.
  • Đáp ứng lưu lượng truy cập lớn.

Bộ nhớ cache trong Hibernate

Hibernate Cache (Bộ nhớ đệm) là nhằm tối ưu hóa hiệu của suất ứng dụng. Nó nằm giữa ứng dụng và cơ sở dữ liệu để tránh số lượng lượt truy cập cơ sở dữ liệu càng nhiều càng tốt để cung cấp cho một hiệu suất tốt hơn cho các ứng dụng.

Hibernate Cache

Các kiểu bộ nhớ cache trong Hibernate:

  • First-level Cache – L1 Cache (Bộ nhớ cache cấp một) : bộ nhớ cache ở mức Session.
  • Second-level Cache – L2 Cache (Bộ nhớ cache cấp hai) : bộ nhớ cache ở mức Session Factory.
  • Query Cache (Bộ nhớ cache cấp truy vấn) : cache các kết quả truy vấn kết hợp chặt chẽ với L2 Cache.

First-level Cache – L1 Cache (Bộ nhớ cache cấp một)

L1 Cache là bộ nhớ cache Session và là một bộ nhớ cache bắt buộc thông qua đó tất cả các yêu cầu phải vượt qua. Đối tượng Session giữ một đối tượng thuộc quyền sở hữu của nó trước khi commit nó vào cơ sở dữ liệu.

Nếu có nhiều yêu cầu cập nhật cho một đối tượng, Hibernate cố gắng trì hoãn việc cập nhật càng lâu càng tốt để giảm số lượng các câu lệnh SQL cập nhật đã gởi. Nếu chúng ta đóng session, tất cả các đối tượng được lưu trữ trong bộ nhớ cache cũng sẽ bị mất và vẫn tiếp tục lưu trữ hoặc cập nhật trong cơ sở dữ liệu.

Một số đặc điểm cần lưu ý:

  • First Level Cache được kết hợp với đối tượng Session và các đối tượng session khác trong ứng dụng không thể “nhìn thấy” hay làm ảnh hưởng.
  • Phạm vi của cách đối tượng cache này là session. Khi một session bị đóng lại, các đối tượng cache thuộc session đó sẽ vĩnh viễn bị mất đi.
  • First Level Cache được enable mặc định trong Hibernate và không có cách nào để disable nó cả.
  • Khi chúng ta truy vấn 1 Entity lần đầu tiên, nó sẽ được lấy về từ database và được lữu trữ trong bộ nhớ của first-level cache, cái mà được liên kết với đối tượng hibernate session.
  • Nếu chúng ta truy vấn lại cùng 1 Entity với cùng session, nó sẽ được load từ trong cache thay vì việc thực thi lại câu truy vấn SQL.
  • Entity được load có thể bị xóa khỏi session, khỏi bộ nhớ first level cache bằng việc sử dụng phuơng thức evict(entity). Như vậy, vào lần tiếp theo ta truy vấn thực thể đó, nó sẽ được lấy từ database (thay vì bộ nhớ cache).
  • Toàn bộ bộ nhớ cache của session có thể bị xoá thông qua phuơng thức clear().
  • Có thể kiểm tra Entity được cache trong session hay chưa thông qua phương thức contains().
  • Do Hibernate cache tất cả các đối tượng vào L1 Cache của session, trong khi chạy truy vấn hàng loạt (bulk queries) hoặc cập nhật hàng loạt (batch updates), nó cần thiết để xóa bộ đệm theo các khoảng thời gian nhất định để tránh các vấn đề về bộ nhớ.

Ví dụ First-level Cache

Ví dụ lấy 1 Entity nhiều lần

try (Session session = HibernateUtils.getSessionFactory().openSession();) {
session.beginTransaction();

for(int i = 0; i < 5; i++) {
Category cat = session.get(Category.class, 1L);
System.out.println(cat.getName());
}

session.getTransaction().commit();
}

Output:

Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
Hibernate cache by gpcoder
Hibernate cache by gpcoder
Hibernate cache by gpcoder
Hibernate cache by gpcoder
Hibernate cache by gpcoder

Như bạn thấy SQL chỉ được thực thi 1 lần, mặc dù chúng ta gọi đến 5 lần do Hibernate đã giúp chúng ta cache lại.

Ví dụ lấy 1 Entity trên nhiều Session khác nhau

try (Session session1 = HibernateUtils.getSessionFactory().openSession();
Session session2 = HibernateUtils.getSessionFactory().openSession();) {

Category cat1_1st = session1.get(Category.class, 1L);
System.out.println("Session 1 at 1st time: " + cat1_1st.getName());

Category cat1_2nd = session1.get(Category.class, 1L);
System.out.println("Session 1 at 2nd time: " + cat1_2nd.getName());

Category cat2 = session2.get(Category.class, 1L);
System.out.println("Session 2: " + cat2.getName());
}

Output:

Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
Session 1 at 1st time: Hibernate cache by gpcoder
Session 1 at 2nd time: Hibernate cache by gpcoder
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
Session 2: Hibernate cache by gpcoder

Như bạn thấy có 2 SQL được thực thi cho mỗi Session khác nhau mặc dù truy xuất cùng 1 Entity.

Ví dụ xoá L1 cache

try (Session session = HibernateUtils.getSessionFactory().openSession();) {
// Begin a unit of work
session.beginTransaction();

User user1 = session.get(User.class, 15L);
System.out.println("user1: " + user1.getFullname());

Category cat1 = session.get(Category.class, 1L);
System.out.println("cat1: " + cat1.getName());

Category cat2 = session.get(Category.class, 1L);
System.out.println("cat2: " + cat2.getName()); // Get from cache

session.evict(cat1); // Remove Category Entity form cache

User user2 = session.get(User.class, 15L);
System.out.println("user2: " + user2.getFullname()); // Get from cache

Category cat3 = session.get(Category.class, 1L);
System.out.println("cat3: " + cat3.getName()); // Get from database because Category entity already evicted

session.clear(); // Remove all Entities from cache

User user3 = session.get(User.class, 15L);
System.out.println("user3: " + user3.getFullname()); // Get from database because User entity already cleared

Category cat4 = session.get(Category.class, 1L);
System.out.println("cat4: " + cat4.getName()); // Get from database because Category entity already cleared
}

Output:

Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
user1: gpcoder user
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
cat1: Hibernate cache by gpcoder
cat2: Hibernate cache by gpcoder
user2: gpcoder user
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
cat3: Hibernate cache by gpcoder
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
user3: gpcoder user
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
cat4: Hibernate cache by gpcoder

Như bạn thấy, phương thức evict() có thể được sử dụng để xoá cache cho 1 đối tượng. Phương thức clear() có thể được sử dụng để xoá tất cả đối tượng.

Second-level Cache – L2 Cache (Bộ nhớ cache cấp hai)

L2 Cache là một bộ nhớ cache tùy chọn (optional), không được enable by default.

Phạm vi ảnh hưởng của L1 Cache là session, nghĩa là khi gọi get một đối tượng trong session, thì nó sẽ chỉ tìm đối tượng trong session đó và trong trường hợp session không có, nó sẽ thực thi câu lệnh truy vấn tới database nếu không có L2 Cache. Trong trường hợp chúng ta có cấu hình L2 Cache thì Hibrernate sẽ thực hiện xác định vị trí một đối tượng trong L2 Cahce trước khi thực thi câu lệnh truy vấn đến database.

Phạm vi lưu trữ đối tượng được mở rộng hơn trong L2 Cache, sang mức SessionFactory thay vì Session như L1 Cache.

Hibernate cung cấp một interface org.hibernate.cache.CacheProvider, bên thứ 3 cần implements để cung cấp Hibernate với một xử lý để cài đăt bộ nhớ cache.

Việc setup L2 Cache sẽ được thực hiện trong 2 bước:

  • Đầu tiên là việc define cache concurrency strategy (chiến lược truy cập đồng thời) nào được sử dụng.
  • Tiếp theo, đó là việc cầu hình các attribute cho cache expiration (hết hạn) và cache vật lý bằng cách sử dụng cache provider.

Cache Concurrency Strategy

Chiến lược truy cập đồng thời là bộ điều chỉnh có trách nhiệm lưu trữ các mục dữ liệu trong bộ nhớ cache và lấy chúng từ bộ nhớ cache. Nếu muốn kích hoạt bộ nhớ cache cấp hai, bạn sẽ phải quyết định, đối với mỗi lớp và collection persistent, mà chiến lược truy cập đồng thời vào bộ nhớ cache để sử dụng.

  • Read-only (READ_ONLY): Chiến lược lưu trữ này nên được sử dụng cho các đối tượng liên tục sẽ luôn đọc nhưng không bao giờ cập nhật. Nó phù hợp cho việc đọc và lưu cấu hình ứng dụng và các dữ liệu tĩnh khác không bao giờ được cập nhật. Đây là chiến lược đơn giản nhất với hiệu suất tốt nhất vì không có quá trình tải để kiểm tra xem đối tượng có được cập nhật trong cơ sở dữ liệu hay không.
  • Nonstrict-read-write (NONSTRICT_READ_WRITE): cơ chế này không đảm bảo tính nhất quán giữa bộ nhớ cache và cơ sở dữ liệu. Sử dụng chiến lược này nếu dữ liệu hầu như không thay đổi và trong trường hợp thay đổi thì sự không nhất quán đó cũng không phải là vấn đề.
  • Read-write (READ_WRITE):
    • Cơ chế này đảm bảo tính nhất quán dữ liệu cao bằng việc sử dụng soft lock. Khi một Entity đã cache bị update, một soft lock được lưu lại trong cache cho entity và nó sẽ được giải phóng (release) khi transaction được commit. Tất cả các transaction nếu truy cập vào các đối tượng đang bị soft block sẽ được lấy trực tiếp từ cơ sở dữ liệu.
    • Loại này phù hợp cho các đối tượng liên tục có thể được cập nhật bởi ứng dụng Hibernate. Tuy nhiên, nếu dữ liệu được cập nhật thông qua  backend hoặc các application khác, thì không có cách nào Hibernate biết về nó và dữ liệu có thể bị cũ. Vì vậy, trong khi sử dụng chiến lược này, hãy đảm bảo bạn đang sử dụng API Hibernate để cập nhật dữ liệu.
  • Transactional (TRANSACTIONAL): Cung cấp cấp bộ đệm transaction đầy đủ, nghĩa là một thay đổi trong Entity được lưu trong bộ nhớ cache được được đảm bảo khôi phục trong cả cơ sở dữ liệu và bộ đệm trong cùng một transaction.

Cache provider

Bước tiếp theo sau khi lựa chọn Cache Concurrency Strategy, chúng ta cần chọn lựa một Cache Provider duy nhất cho toàn bộ ứng dụng.

Một số Cache Provider thông dụng:

  • EH Cache : Nó có thể cache trong bộ nhớ RAM hoặc trên đĩa cứng và clustered caching và nó hỗ trợ bộ nhớ cache kết quả truy vấn Hibernate tuỳ chọn.
  • OS Cache : Hỗ trợ bộ nhớ đệm vào bộ nhớ RAM và đĩa cứng trong một JVM duy nhất, với một tập hợp đầy đủ các chính sách hết hạn và hỗ trợ bộ nhớ truy vấn.
  • Swarm Cache : Một bộ nhớ cache cluster dựa trên JGroups. Nó sử dụng huỷ bỏ hiệu lực clustered nhưng không hỗ trợ bộ nhớ cache truy vấn Hibernate.
  • JBoss Cache : Một bộ nhớ cache cluster được sao chép hoàn toàn hợp lệ được transaction dựa trên thư viện đa nhóm JGroups. Nó hỗ trợ nhân bản hoặc hủy bỏ hiệu lực, giao tiếp đồng bộ hoặc không đồng bộ, và optimistic, pessimistic locking. Bộ nhớ truy vấn cache Hibernate được hỗ trợ.

Mỗi Cache Provider không tương thích với mọi Cache Concurrency Strategy. Ma trận sẽ giúp bạn có một sự chọn phù hợp:

PROVIDER \ STRATEGY READ-ONLY NONSTRICTREAD-WRITE READ-WRITE TRANSACTIONAL
EH Cache X X X
OS Cache X X X
Swarm Cache X X
JBoss Cache X X

Cách thức hoạt động L2 Cache

  • Bất cứ khi nào hibernate session cố gắng load một Entity, nơi đầu tiên nó tìm L1 Cache (được liên kết với session cụ thể).
  • Nếu Entity được lưu trong L1 Cache, nó được trả về như là kết quả của phương thức load.
  • Nếu không tìm thấy, thì L2 Cache sẽ được tìm kiếm.
  • Nếu tìm thấy trong L2 Cache, nó được trả về do kết quả của phương thức load. Nhưng, trước khi trả lại Entity, nó cũng được lưu L1 Cache để lệnh gọi tiếp theo sẽ trả về thực thể từ chính L1 Cache và sẽ không cần phải chuyển sang tìm ở L2 Cache nữa.
  • Nếu không tìm thấy trong L2 Cache, thì truy vấn SQL đến cơ sở dữ liệu được thực thi và Entity được lưu trữ trong cả hai cấp bộ đệm, trước khi trả về dưới dạng phản hồi của phương thức load.
  • L2 Cache xác nhận chính nó cho các Entity được sửa đổi, nếu việc sửa đổi đã được thực hiện thông qua các API Hibernate Session.
  • Nếu một số người dùng hoặc quá trình thực hiện thay đổi trực tiếp trong cơ sở dữ liệu, thì không có cách nào mà L2 Cache cập nhật cho đến khi thời gian của ToToLiveSeconds đã vượt qua cho vùng bộ đệm đó. Trong trường hợp này, bạn nên vô hiệu hóa toàn bộ bộ đệm và để hibernate xây dựng bộ đệm của nó một lần nữa.

Enable L2 Cache

Để bật L2 Cache trong Hibernate, chỉ cần cấu hình 2 thuộc tính:

  • hibernate.cache.use_second_level_cache : để báo với Hibernate rằng chúng ta có dùng L2 Cache hay không.
  • hibernate.cache.region.factory_class : để chỉ định tên lớp Region Factory của Cache Provider.

Nếu muốn Query Cache, chúng ta có thể thêm thuộc tính: hibernate.cache.use_query_cache

Ví dụ Second-level Cache sử dụng EHCache

Trong bài này, chúng ta chọn EHCache làm Cache Provider cho ứng dụng.

Thêm EHCache dependency library:

<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --> <dependency>     <groupId>org.hibernate</groupId>     <artifactId>hibernate-core</artifactId>     <version>5.4.7.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache --> <dependency>     <groupId>org.hibernate</groupId>     <artifactId>hibernate-ehcache</artifactId>     <version>5.4.7.Final</version> </dependency>

Mở file cấu hình hibernate.cfg.xml và thêm cấu hình cache như sau:

<hibernate-configuration>     <session-factory>         <!-- Database setting -->         <!-- enable second level cache -->         <property name="cache.use_second_level_cache">true</property>         <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>              </session-factory> </hibernate-configuration>

Tiếp theo, chúng ta cần phải báo với Hibernate rằng các Entity của mình có thể được sử dụng với L2 Cache. Chẳng hạn tôi cần cache Category như sau:

package com.gpcoder.entities;

import lombok.Data;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import javax.persistence.*;
import java.util.Set;

@Data
@Entity
@Table
@Cacheable
@Cache(usage= CacheConcurrencyStrategy.READ_ONLY)
public class Category implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "category")
@OrderBy("title")
private Set posts;
}

Chạy lại Ví dụ lấy 1 Entity trên nhiều Session khác nhau ở trên:

try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session1 = sessionFactory.openSession();
Session session2 = sessionFactory.openSession();) {

Category cat1_1st = session1.get(Category.class, 1L);
System.out.println("Session 1 at 1st time: " + cat1_1st.getName());

Category cat1_2nd = session1.get(Category.class, 1L);
System.out.println("Session 1 at 2nd time: " + cat1_2nd.getName());

Category cat2 = session2.get(Category.class, 1L);
System.out.println("Session 2: " + cat2.getName());
}

Output:

Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
Session 1 at 1st time: Hibernate cache by gpcoder
Session 1 at 2nd time: Hibernate cache by gpcoder
Session 2: Hibernate cache by gpcoder

Như bạn thấy, bây giờ SQL chỉ được thực thi một lần, mặc dù ở 2 session khác nhau do nó đã được Cache ở L2.

Lưu ý: Collection mặc định sẽ không được cache, chúng ta cần khai báo tuờng minh nếu chúng ta cần cache nó lại. Chẳng hạn, list posts của Category trên sẽ không được Cache.

Ví dụ cơ chế hoạt động L2 Cache

Trong ví dụ này, mình cần enable thống kê (Statistic) của Hibernate L2 Cache:

  • getSecondLevelCacheHitCount() : được sử dụng để lấy số lần Entity được lấy từ L2 Cache.
  • getSecondLevelCachePutCount() : được sử dụng để lấy số lần Entity được đưa vào L2 Cache.
public static void main(String[] args) {
try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session1 = sessionFactory.openSession();
Session session2 = sessionFactory.openSession();) {

Statistics stats = sessionFactory.getStatistics();
System.out.println("Stats enabled = " + stats.isStatisticsEnabled());
stats.setStatisticsEnabled(true);
System.out.println("Stats enabled = " + stats.isStatisticsEnabled());

printStats(stats);

System.out.println("--- 1 ---");
Category cat1 = session1.get(Category.class, 1L);
System.out.println("cat1: " + cat1.getName()); // Get from db
printStats(stats);

System.out.println("--- 2 ---");
Category cat2 = session1.get(Category.class, 1L);
System.out.println("cat2: " + cat2.getName()); // Get from L1 Cache
printStats(stats);

System.out.println("--- 3 ---");
Category cat3 = session2.get(Category.class, 1L);
System.out.println("cat3: " + cat3.getName()); // Get from L2 cache
printStats(stats);

System.out.println("--- 4 ---");
Category cat4 = session2.get(Category.class, 1L);
System.out.println("cat4: " + cat4.getName()); // Get from L1 cache
printStats(stats);

System.out.println("--- 5 ---");
Category cat5 = session1.get(Category.class, 2L);
System.out.println("cat5: " + cat5.getName()); // Get from db
printStats(stats);

System.out.println("--- 6 ---");
Category cat6 = session2.get(Category.class, 2L);
System.out.println("cat6: " + cat6.getName()); // Get from L2 cache
printStats(stats);
}
}

private static void printStats(Statistics stats) {
System.out.println("Second Level Hit Count = " + stats.getSecondLevelCacheHitCount());
System.out.println("Second Level Put Count = " + stats.getSecondLevelCachePutCount());
}

Output:

Stats enabled = false
Stats enabled = true
Fetch Count = 0
Second Level Hit Count = 0
Second Level Put Count = 0
--- 1 ---
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
cat1: Hibernate cache by gpcoder
Fetch Count = 0
Second Level Hit Count = 0
Second Level Put Count = 1
--- 2 ---
cat2: Hibernate cache by gpcoder
Fetch Count = 0
Second Level Hit Count = 0
Second Level Put Count = 1
--- 3 ---
cat3: Hibernate cache by gpcoder
Fetch Count = 0
Second Level Hit Count = 1
Second Level Put Count = 1
--- 4 ---
cat4: Hibernate cache by gpcoder
Fetch Count = 0
Second Level Hit Count = 1
Second Level Put Count = 1
--- 5 ---
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
cat5: Hibernate Framework
Fetch Count = 0
Second Level Hit Count = 1
Second Level Put Count = 2
--- 6 ---
cat6: Hibernate Framework
Fetch Count = 0
Second Level Hit Count = 2
Second Level Put Count = 2

Như bạn thấy:

  • (1) : cả L1 và L2 cache không có gì, nên SQL được thực thì để lấy dữ liệu từ database. Sau đó nó được lưu tại L1 Cache của session1 và L2 Cache.
  • (2) : Dữ liệu được lấy trực tiếp của L1 Cache, nên Hit=0, Put=1.
  • (3) : Dữ liệu lấy từ L2 Cache. Do session2 không chứa Entity đã lấy từ session1, nó tìm ở L2 Cache và lấy từ Cache, không truy xuất Database. Sau đó, dữ liệu được cache lại ở L1 Cache của session2. Bây giờ: Hit=1, Put=1.
  • (4) : Lần tiếp theo dữ liệu đã được cache lại ở L1 Cache của session2, nó không cần tìm ở L2 Cache, nên Hit=1, Put=1.
  • (5) : Cả L1 và L2 cache không chứa Category=2, nên lấy dữ liệu từ database. Sau đó nó được lưu tại L1 Cache của session1 và L2 Cache. Bây giờ: Hit=1, Put=2.
  • (6) : Tương tự, L1 Cache của session2 không chứa dữ liệu Category=2, nên nó tìm và truy xuất từ L2 Cache. Bây giờ: Hit=2, Put=2.

Ví dụ xoá L2 Cache

try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session = sessionFactory.openSession();) {
// Begin a unit of work
session.beginTransaction();

Category cat1 = session.get(Category.class, 1L);
System.out.println("cat1: " + cat1.getName());

Category cat2 = session.get(Category.class, 1L);
System.out.println("cat2: " + cat2.getName()); // Get from cache

session.evict(cat1); // Remove Category Entity from L1 cache

Category cat3 = session.get(Category.class, 1L);
System.out.println("cat3: " + cat3.getName()); // Get from cache

sessionFactory.getCache().evict(Category.class, cat3); // Clear cache of one Category Entity

Category cat4 = session.get(Category.class, 1L);
System.out.println("cat4: " + cat4.getName()); // Get from database because Category entity already cleared
}

Output:

Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
cat1: Hibernate cache by gpcoder
cat2: Hibernate cache by gpcoder
cat3: Hibernate cache by gpcoder
Hibernate: select posts0_.category_id as category4_1_0_, posts0_.id as id1_1_0_, posts0_.id as id1_1_1_, posts0_.category_id as category4_1_1_, posts0_.content as content2_1_1_, posts0_.title as title3_1_1_, posts0_.user_id as user_id5_1_1_ from Post posts0_ where posts0_.category_id=? order by posts0_.title
cat4: Hibernate cache by gpcoder

Như bạn thấy phương thức session.evict() không có tác dụng với L2 Cache, để xoá cache ở L2 Cache chúng ta cần gọi evict() từ cache của Session Factory.

Cache Management

Nếu không cấu hình chính sách hết hạn và gỡ bỏ, bộ nhớ cache có thể phát triển vô hạn và cuối cùng tiêu thụ hết bộ nhớ hiện có. Trong hầu hết các trường hợp, Hibernate trao nhiệm vụ đó cho Cache Provider.

EHCache có file cấu hình riêng của mình, đó là ehcache.xml nên để chỉ định các thuộc tính của vùng nhớ cache, thời gian lưu giữ, số lượng instance, …

Ví dụ:

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true">     <diskStore path="java.io.tmpdir/ehcache" />     <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="true">         <persistence strategy="localTempSwap" />     </defaultCache>     <cache name="com.gpcoder.entities.Category" maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="2" timeToLiveSeconds="10">         <persistence strategy="localTempSwap" />     </cache>     <cache name="org.hibernate.cache.internal.StandardQueryCache" maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120">         <persistence strategy="localTempSwap" />     </cache> </ehcache>

EHCache bao gồm rất nhiều cấu hình, tôi chỉ giới thiệu với các bạn một vài cấu hình cơ bản, còn rất nhiều cấu hình khác các bạn xem thêm trên EHCache Configuration document.

  • diskStore : EHCache lưu dữ liệu vào bộ nhớ nhưng khi nó bắt đầu đầy, nó bắt đầu ghi dữ liệu vào file system. Chúng ta sử dụng thuộc tính này để xác định vị trí nơi EHCache sẽ ghi dữ liệu khi đầy.
  • defaultCache : được sử dụng khi một đối tượng cần được lưu trữ và không có vùng lưu trữ được xác định cho riêng cho nó.
    • timeToIdleSeconds : bộ đệm sẽ hết hạn sau một khoảng thời gian cố định sau thời gian chúng được truy cập lần cuối.
    • timeToLiveSeconds : bộ đệm sẽ hết hạn sau một khoảng thời gian cố định sau khi tạo.
    • eternal: bộ đệm sẽ không bao giờ hết hạn.
  • cache name=”com.gpcoder.entities.Category” : được sử dụng để xác định cấu hình riêng cho một Entity.
  • org.hibernate.cache.internal.StandardQueryCache : Cấu hình vùng đệm cho Query Cache.

Tiếp theo, mở file cấu hình hibernate.cfg.xml và thêm cấu hình EHCache như sau:

<!-- enable second level cache --> <property name="cache.use_second_level_cache">true</property> <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <property name="net.sf.ehcache.configurationResourceName">/myehcache.xml</property>

Ví dụ: chúng ta cấu hình Cache cho Category sẽ hết hạn sau 2 giây sau thời gian chúng được truy cập lần cuối và 10 giây sau khi tạo.

private static void printStats(Statistics stats) {
System.out.println("Second Level Hit Count = " + stats.getSecondLevelCacheHitCount());
System.out.println("Second Level Put Count = " + stats.getSecondLevelCachePutCount());
}

public static void main(String[] args) {
try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session1 = sessionFactory.openSession();
Session session2 = sessionFactory.openSession();) {

Statistics stats = sessionFactory.getStatistics();
System.out.println("Stats enabled = " + stats.isStatisticsEnabled());
stats.setStatisticsEnabled(true);
System.out.println("Stats enabled = " + stats.isStatisticsEnabled());

printStats(stats);

System.out.println("--- 1 ---");
Category cat1 = session1.get(Category.class,1L);
System.out.println(cat1.getName());
printStats(stats);

System.out.println("--- 2 ---");
Category cat2 = session2.get(Category.class,1L);
System.out.println(cat2.getName());
printStats(stats);

TimeUnit.SECONDS.sleep(3);

System.out.println("--- 3 ---");
Category cat3 = session1.get(Category.class,3L);
System.out.println(cat3.getName());
printStats(stats);

} catch (InterruptedException e) {
e.printStackTrace();
}
}

Output:

Stats enabled = false
Stats enabled = true
Second Level Hit Count = 0
Second Level Put Count = 0
--- 1 ---
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
Hibernate cache by gpcoder
Second Level Hit Count = 0
Second Level Put Count = 1
--- 2 ---
Hibernate cache by gpcoder
Second Level Hit Count = 1
Second Level Put Count = 1
--- 3 ---
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
Java
Second Level Hit Count = 1
Second Level Put Count = 2

Như bạn thấy:

  • (1) : Dữ liệu được lấy từ database và lưu vào L2 Cache.
  • (2) : Dữ liệu được lấy từ L2 Cache.
  • (3) : Dữ liệu được lấy từ database, do sau khoảng 3 giây sau mới có request lấy dữ liệu, nên nó đã bị xoá khỏi cache từ trước (timeToIdleSeconds=2).

Query Cache

Cache các kết quả truy vấn kết hợp chặt chẽ với L2 Cache.

Đây là tính năng tùy chọn và yêu cầu thêm hai vùng bộ nhớ cache vật lý giữ kết quả truy vấn và các mốc thời gian khi một bảng được cập nhật lần cuối. Điều này chỉ hữu ích cho các truy vấn được chạy thường xuyên với các tham số giống nhau.

Để sử dụng Query Cache, mở file cấu hình hibernate.cfg.xml và thêm cấu hình sau:

<property name="cache.use_query_cache">true</property>

Ví dụ:

try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session1 = sessionFactory.openSession();) {

String hql = "FROM Category cat WHERE cat.id = :id";
Query query = session1.createQuery(hql, Category.class);
query.setCacheable(true);
query.setCacheRegion(Category.class.getCanonicalName());
Category cat1 = query.setParameter("id", 1L).uniqueResult();
System.out.println("cat1: " + cat1.getName());

Category cat2 = query.setParameter("id", 1L).uniqueResult();
System.out.println("cat2: " + cat2.getName());
}

Output:

Hibernate: select category0_.id as id1_0_, category0_.name as name2_0_ from Category category0_ where category0_.id=?
cat1: Hibernate cache by gpcoder
cat2: Hibernate cache by gpcoder

Bài viết đến đây là hết. Hy vọng giúp ích cho các bạn improve performance của ứng dụng mình tốt hơn. Hẹn gặp lại ở các bài viết tiếp theo!!!

Tài liệu tham khảo:

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

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

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

Software Architecture Timeline

software architecture timeline

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

Và điều đầu tiên đề cập đến trong bài viết này tôi gọi là “lược sử (timeline) về kiến trúc phần mềm” nơi tác giả liệt kê các mốc chính về các mô hình lập trình, các kiểu thiết kế nổi bật từ thuở sơ khai đến hiện tại, có thể kể đến như:

  10 Công cụ Go-To Tech dành riêng cho các Software Developer
  Biến Git và GitHub trở thành công cụ đắc lực cho Software Engineer
  • 1950S

    •   Non-structured Programming
    • ~1951 – Assembly
  • 1960S

    •   Structured Programming
    •   Layering: 1 tier with the UI, Business Logic and Data Storage
    • ~1958 – Algol
  • 1970S

    •   Procedural / Functional Programming
    • ~1970 – Pascal
    • ~1972 – C
    •   1979 – Model-View-Controller
  • 1980S

    •  Object Oriented Programming (first thoughts were in the late 1960s, though)
    •   Layering: 2 tier, the 1st tier with the UI, the 2nd tier with Business Logic and Data Storage
    • ~1980 – C++
    •   CORBA – Common Object Request Broker Architecture (though the first stable version was only out in 1991, the first usages were during the 1980s)
    • ~1986 – Erlang
    • ~1987 – Perl
    •   1987 – PAC aka Hierarchical Model-View-Controller
    •   1988 – LSP (~SOLID)
  • 1990S

    •   Layering: 3 tier, the 1st tier with the UI, the 2nd tier Business Logic (and the UI presentation logic in case of a browser as client), the 3rd tier with the Data Storage
    • ~1991 – Message Bus
    • ~1991 – Python
    •   1992 – Entity-Boundary-Interactor Architecture aka EBC aka EIC
    • ~1993 – Ruby
    • ~1995 – Delphi, Java, Javascript, PHP
    •   1996 – Model-View-Presenter
    •   1996 – OCP, ISP, DIP (~SOLID), REP, CRP, CCP, ADP
    •   1997 – SDP, SAP
    • ~1997 – Aspect Oriented Programming
    • ~1997 – Web Services
    • ~1997 – ESB – Enterprise Service Bus (although the book that coined the term was published in 2004, the concept was already used before)

Tham khảo tuyển dụng software engineer lương cao trên TopDev

  • 2000S

    • 2002 – SRP (~SOLID)
    • 2003 – Domain-Driven Design
    • 2005 – Model-View-ViewModel
    • 2005 – Ports & Adapters Architecture aka Hexagonal Architecture
    • 2006? – CQRS & ES (Command Query Responsibility Segregation & Event Sourcing)
    • 2008 – Onion Architecture
    • 2009 – Microservices (at Netflix)
  • 2010S

    • 2010 – Data-Context-Interaction Architecture 
    • 2012 – Clean Architecture
    • 2014 – C4 Model

Giống như ông bà ta thường nói, không biết lịch sử nước nhà thì cũng như là người mất gốc. Bằng cách nắm được timeline của một việc nào đó sẽ giúp chúng ta có cái nhìn toàn cảnh đầu tiên nhất về sự việc đó, bằng không sẽ rất khó khăn khi liên kết các mắt xích của vấn đề lại với nhau.

Trong bài tiếp theo, chúng ta sẽ tìm hiểu kỹ hơn về các khái niệm căn bản trong kiến trúc phần mềm. Sẽ thật là thiếu sót khi làm về một việc nào đó mà không thể đưa ra định nghĩa rõ ràng về nó phải không nào. See you then.

Đây là bài viết trong loạt bài viết về “Tổng quan về sự phát triển của kiến trúc phần mềm“. Đây là loạt bài viết chủ yếu giới thiệu về một số mô hình kiến trúc phần mềm hay nói đúng hơn là sự phát triển của chúng qua từng giai đoạn, qua đó giúp chúng ta có cái nhìn tổng quát, up-to-date và là roadmap để bắt đầu hành trình chinh phục (đào sâu) thế giới của những bản thiết kế với vai trò là những kỹ sư và kiến trúc sư phần mềm đam mê với nghề.

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

Giới thiệu về WebJars

Giới thiệu về WebJars

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

Không biết các bạn khi work với các Java web application có sử dụng các front-end framework như JQuery, Bootstrap, … như thế nào, nhưng đối với mình, việc quản lý, cấu hình để sử dụng các framework đôi khi là cả một vấn đề. Đơn cử như việc sử dụng thư viện Backbone.JS, thư viện này có một dependency là thư viện Underscore.JS, muốn sử dụng Backbone.JS thì chúng ta phải include thêm thư viện Underscore.JS. Việc để các tập tin .js của các framework ở đâu cũng làm mình cũng phải suy nghĩ, …

Những vấn đề như mình đề cập ở trên, chúng ta có thể dễ dàng giải quyết với WebJars. WebJars là một bộ các client-side web libraries được đóng gói trong các tập tin JAR, giúp chúng ta có thể dễ dàng quản lý và sử dụng các libraries, framework phổ biến của front-end như JQuery, Bootstrap, … trong các ứng dụng Java web application. Các bạn có thể sử dụng Maven hoặc Gradle để quản lý các dependencies này. WebJars hoạt động tốt với hầu hết các web framework của Java như Spring framework chẳng hạn, … Trong bài viết này, mình sẽ hướng dẫn các bạn cách sử dụng WebJars như thế nào các bạn nhé!

Đầu tiên, mình sẽ tạo một Spring Boot với Web dependency để làm ví dụ. Như mình đã nói, WebJars hoạt động tốt với hầu hết các Java web framework nên các bạn có thể sử dụng nó trong bất cứ Java web project nào nha các bạn.

Giới thiệu về WebJars

Để làm ví dụ, mình sẽ thêm WebJars dependency cho JQuery, Bootstrap và Backbone.JS như sau:

<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>bootstrap</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>backbone</artifactId>
<version>1.4.0</version>
</dependency>

Bởi vì Backbone.JS có dependency là Underscore.JS nên các bạn sẽ thấy Underscore.JS cũng được include vào project mà chúng ta không cần phải làm gì cả:

Rất tiện phải không các bạn?

Để khai báo sử dụng các front-end, framework mà mình đã thêm, mình sẽ tạo mới tập tin app.js và index.html trong thư mục src/main/resource/static với nội dung như sau:

index.html:

<!DOCTYPE html>
<html>
<head>
<title>Hello WebJars</title>
<script src="/webjars/jquery/3.6.0/dist/jquery.min.js"></script>
<script src="/webjars/bootstrap/5.0.1/dist/js/bootstrap.min.js"></script>
<script src="/webjars/underscore/1.13.1/underscore-min.js"></script>
<script src="/webjars/backbone/1.4.0/backbone-min.js"></script>
<script src="/app.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap/5.0.1/dist/css/bootstrap.min.css" />
</head>
<body>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com"> 
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password"> 
<label for="floatingPassword">Password</label>
</div>
</body>
</html>

Đường dẫn đến các tập tin .js khai báo trong thẻ <script> hay .css trong thẻ <link> sẽ phụ thuộc vào cách mà các tập tin này được chứa trong tập tin .jar của WebJars như thế nào. Mình lấy đơn cử một ví dụ về thư viện JQuery, các bạn sẽ thấy tập tin jquery.min.js được chứa trong tập tin jquery-3.6.0.jar như sau:

So sánh cách mình khai báo ở trên, các bạn sẽ thấy giá trị của attribute src trong thẻ <script> sẽ bắt đầu với thư mục webjars nằm trong tập tin .jar file. Tương tự thì attribute href của thẻ <link> thì cũng vậy.

app.js

$(document).ready(function() {
alert("Hello WebJars!");
});

var View = Backbone.View.extend({
initialize: function() {
alert("Hello In Backbone View");
}
})
var view = new View({});

Bây giờ nếu chạy ứng dụng, các bạn sẽ thấy 2 alert message được hiển thị.

Một nằm trong code của Backbone.JS:

Một là code của JQuery:

Giới thiệu về WebJars

Và hiển thị HTML, CSS của Bootstrap:

Rất ổn phải không các bạn?

Nếu các bạn để ý, với cách khai báo đường dẫn tới các tập tin .js hay .css ở trên, sẽ rất bất tiện nếu chúng ta upgrade version của các libraries này. Chúng ta sẽ phải thay đổi code để cập nhập đường dẫn theo version mới vì như các bạn thấy, trong đường dẫn tới các tập tin .js hay .css, bao gồm luôn cả version. Để giải quyết vấn đề này, các bạn có thể thêm một dependency của WebJars là:

<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>

Lúc này, chúng ta có thể khai báo các đường dẫn tới các tập tin .js hay .css mà không cần version như sau:

<!DOCTYPE html>
<html>
<head>
<title>Hello WebJars</title>
<script src="/webjars/jquery/dist/jquery.min.js"></script>
<script src="/webjars/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/webjars/underscore/underscore-min.js"></script>
<script src="/webjars/backbone/backbone-min.js"></script>
<script src="/app.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap/dist/css/bootstrap.min.css" />
</head>
<body>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com"> 
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password"> 
<label for="floatingPassword">Password</label>
</div>
</body>
</html>

Kết quả vẫn tương tự nếu các bạn chạy lại ứng dụng.

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

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

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

Ranh giới mong manh giữa NGƯỜI và MÁY (AI, ML, DL và NN)

Ranh giới mong manh giữa NGƯỜI và MÁY (AI, ML, DL và NN)

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

AI (Trí tuệ nhân tạo), Machine Learning (học máy), Neural Network (mạng nơ-ron nhân tạo) và Deep Learning (học sâu) – Ranh giới mong manh giữa người và máy !

Vâng, trong những năm gần đây thì những thuật ngữ công nghệ như AI, ML, DL, NN xuất hiện ngày càng nhiều và ngày càng hào nhoáng hơn.

AI cùng với Machine Learning, Deep Learning và Neural Network ! Vậy chúng sinh ra để làm màu, hay đó là những công nghệ đột phá của những “bộ óc đầy sạn” ở bên kia thung lũng Silicon?

Riêng đối với AI – trí tuệ nhân tạo thì nó đã không còn là một khái niệm trong phim viễn tưởng nữa rồi, mà mình chắc chắn rằng, nó đang là một phần của cuộc sống hiện đại ngày nay.

  "Làm PM, theo anh không cần biết về code, nhưng phải hiểu về SQL, database, những khái niệm cơ bản của code"
  "Ở Việt Nam, cơ hội để thực sự làm về Trí tuệ nhân tạo còn quá ít, trong khi những thứ mang hình thù và dáng dấp AI thì quá nhiều"

#1. Sơ bộ về AI cùng với: ML, NN, DL

Đầu tiên thì mình sẽ định nghĩa ngắn gọn về các thuật ngữ mình sẽ nói trong bài viết này để các bạn dễ hình dung trước:

AI (Trí tuệ nhân tạo): Quá quen thuộc rồi, một cỗ máy có thể bắt chước hành vi và tư duy của con người. Cái tên của nó đã nói lên được điều đó rồi 🙂

Machine Learning (Học máy): Một tính năng của AI, cho phép các chuyên gia đào tạo cho AI để nó nhận biết các mẫu dữ liệu và dự đoán.

Deep Learning (Học sâu): Là một kỹ thuật nhỏ của Machine Learning, nó cho phép máy có thể tự đào tạo chính mình.

Neural Network (mạng nơ-ron nhân tạo): Tên tiếng anh đầy đủ là Artificial Neural network (ANN) hay còn gọi là mạng thần kinh nhân tạo, đây là một mô hình toán học được xây dựng dựa trên các mạng neural sinh học. Hay nói cách khác, mạng nơ ron nhân tạo được xem là hệ thống của các tế bào thần kinh nhân tạo, bắt bước cách thức hoạt động từ não bộ con người.

“Độ rộng lớn” của các khái niệm này phụ thuộc vào mục tiêu phát triển AI (nó có thể là những công cụ như: giải mã capcha, hay một “trí tuệ” đúng nghĩa: ngang ngửa và thậm chí là ưu việt hơn trí tuệ con người).

Ví dụ như năm 2016, AlphaGo Google đánh thắng cao thủ cờ vây quốc tế người Hàn là Lee Se-Dol. Quá kinh khủng ◔◡◔

Ranh giới mong manh giữa NGƯỜI và MÁY (AI, ML, DL và NN)

Khi đó, thuật ngữ AI, Machine Learning, Deep Learning và Neural Network đã được giới truyền thông sử dụng để mô tả chiến thắng của AlphaGo, và đó chính là chức năng chính của AI.

Nói đúng hơn thì AlphaGo mới chỉ nằm ở dạng AI đơn giản – Artificial Narrow Intelligence (ANI), bởi thế mới nói, 2 dạng cao hơn của AI (AGI và ASI) nó phức tạp đến cỡ nào.

Nhưng chúng thực sự không giống nhau, để dễ hình dung hơn về mối quan hệ của 4 khái niệm trên thì bạn có thể tưởng tượng chúng như được lồng ghép với nhau trong một con lật đật Nga, và khi đó:

  1. AI – ý tưởng xuất hiện sớm nhất- suy nghĩ đầu tiên của nó là con lật đật lớn nhất.
  2. Tiếp đến là Machine Learning – khái niệm xuất hiện sau.
  3. Rồi  mới đến Deep Learning – thứ đang thúc đẩy sự bùng nổ của AI hiện nay, cùng với “Neural Networks” (phần lõi của các thuật toán Deep Learning) là con lật đật nhỏ nhất.

Bây giờ chúng ta sẽ cùng nhau tìm hiểu kỹ hơn về sự liên quan giữa 4 khái niệm này, đầu tiên là AI: Thuật ngữ trí tuệ nhân tạo được ra đời vào năm 1956, khái niệm này có thể coi là khá cũ, nhưng đến năm 2021 này thì nó mới thực sự trở nên phổ biến.

Lí do chính của việc này là trước đây chưa có Big data, các hệ thống thường có ít dữ liệu => các chương trình AI sẽ không có đủ dữ liệu để training/dự đoán kết quả được chính xác.

Nhưng hiện tại thì tình hình đã được cải thiện, lượng dữ liệu tăng lên chóng mặt, đi cùng với đó là khả năng lưu trữ dường như là vô tận (BigData) của các server farm đến từ các ông lớn của thung lũng Silicon: Google, Amazon, Apple, Microsoft…

Ranh giới mong manh giữa NGƯỜI và MÁY (AI, ML, DL và NN)

Thống kê cho thấy đến năm 2020, khối lượng dữ liệu tích lũy sẽ tăng từ 4,4 triệu TB lên tới khoảng 44 triệu TB dữ liệu. Phải nói là kinh khủng khiếp ٩(͡๏̮͡๏)۶, các bạn nên nhớ 1TB là 1000 GB nhé ^^

Song song với đó, chúng ta có thêm những siêu máy tính, những thuật toán phức tạp để có thể xử lý được hết lượng dữ liệu khổng lồ này.

#2. AI (Artificial Intelligence hay Trí tuệ Nhân tạo)

AI là một ngành của khoa học máy tính, là tập hợp của các phương thức tự động hóa các hành vi trí tuệ nâng cao, được đặt trên những nguyên lý, lý thuyết khoa học máy tính vững chắc và phải có khả năng ứng dụng được vào trong cuộc sống (nói theo 1 cách học thuật thì là như thế).

Còn nói theo cách đơn giản hơn thì AI là trí tuệ của máy móc và được tạo ra bởi con người. Trí tuệ này cũng có thể tư duy và học hỏi như trí tuệ tự nhiên của con người vậy. Ngoài ra thì, AI có khả năng xử lý dữ liệu ở quy mô lớn, có hệ thống khoa học và nhanh hơn nhiều so với suy nghĩ của con người.

Một ví dụ về trí tuệ nhân tạo gần gũi với đời sống con người hiện nay đó là Google Home. Vâng, loa thông minh Google Home là món đồ công nghệ tuyệt vời, bạn có thể điều khiển nó bằng giọng nói. Chẳng hạn như bạn có thể nói: “Ok, Google ! thời tiết hôm nay thế nào?”.

Sau đó, Google Home sẽ chuyển giọng nói của bạn thành tín hiệu kỹ thuật số hoặc một dạng tín hiệu mà máy tính có thể hiểu được.

Tiếp đến, phần mềm/ thuật toán đi kèm với Google Home sẽ xử lý thông tin đó để xác định những gì bạn đang hỏi, những thông tin mà bạn đang cần, và vào đâu để lấy được những thông tin đó.

Sau khi đã xử lý xong, nó sẽ trả lời thông tin về nhiệt độ, độ ẩm, vận tốc gió,… ở khu vực mà bạn sinh sống. Ngoài ra, bạn có thể hỏi thêm về: giao thông, chứng khoán, giá vàng,… hôm nay như thế nào bằng cách tương tự như vậy !

Tóm lại, những gì chúng ta đang thực hiện với AI hiện nay nằm trong khái niệm sơ cấp: “AI hẹp” (Narrow AI), công nghệ này có khả năng thực hiện các nhiệm vụ cụ thể một cách tương tự, hoặc tốt hơn con người.

Hiện nay thì ChatBot, hay là các trợ lí ảo như Siri, Alexa, Bixby,… nhìn thì thông minh và phức tạp vậy đấy, nhưng nó chỉ mới thuộc lớp AI cấp thấp này mà thôi, còn lâu mới lên level cao hơn của AI.

Điều khiến trí tuệ nhân tạo nổi trội hơn so với các chương trình máy tính khác là: thay vì phải lập ra những chương trình cụ thể cho mỗi trường hợp khác nhau, thì nay, những cỗ máy này có thể tự học để cải thiện chính nó.

Tính năng này sẽ dẫn chúng ta đến chú lật đật con tiếp theo: “Máy Học” – Machine Learning hình thành vào những năm 80-90, cho phép máy tính hành động/đưa ra quyết định nhờ vào những dữ liệu nạp vào, để thực hiện một nhiệm vụ cụ thể.

Machine Learning cho phép máy tính tự học để tự cải thiện nhiệm vụ mà nó đang làm, mức độ cải thiện sẽ tăng dần theo từng lần thực hiện.. Giống như việc con người chúng ta sẽ rút ra được những kinh nghiệm sau những sai lầm và thất bại vậy.

“ML” sử dụng những thuật toán phân tích thông tin có sẵn => học hỏi từ nó => đưa ra quyết định/dự đoán những thứ có liên quan.

Thay vì tạo ra phần mềm được lập trình 1 là 1, 2 là 2 thì nay máy tính được “Training – huấn luyện” bằng cách sử dụng dữ liệu và các thuật toán để học cách thực hiện/cải thiện hiệu suất thực hiện nhiệm vụ của chính nó.

Nếu thiếu Machine Learning thì AI sẽ bị hạn chế khá nhiều, vì Machine learning cho phép máy tính tăng khả năng tìm ra cách giải quyết mọi thứ mà không cần được lập trình ngay từ đầu.

Một ví dụ về Machine Learning mà có thể bạn cũng đang sử dụng mỗi ngày đó chính là công cụ tìm kiếm của Google, khi bạn thực hiện tìm kiếm trên Google, nó sẽ trả lại rất nhiều kết quả tìm kiếm với từ khóa đó.

Nếu bạn giành nhiều thời gian để xem những kết quả trả về hoặc bạn đã click vào một đường link để đọc tiếp, Google sẽ ghi nhận người này đã dành nhiều thời gian (khoảng 40 giây chẳng hạn) để xem thông tin trả về.

Điều này giúp Google hiểu rằng, thông tin này là phù hợp với từ khóa này hơn cả, nó hữu ích và phù hợp với người tìm kiếm.

Còn ngược lại, nếu bạn chỉ lướt nhanh qua những kết quả trả về, Google sẽ ghi nhận là bạn không quan tâm tới những kết quả này => những kết quả trả về này là không phù hợp với bạn.

Điều này cũng có nghĩa là Machine Learning sẽ phỏng đoán được những gì bạn thích hoặc không thích. Do đó, những lần tìm kiếm sau, bạn sẽ nhận được những kết quả tìm kiếm được điều chỉnh một cách phù hợp hơn !

#3. Deep Learning là gì?

Machine learning lợi hại như vậy, thế còn Deep Learning thì sao?

Deep Learning là tập hợp con của Machine Learning, nó dùng mạng thần kinh nhân tạo để phân tích dữ liệu về nhiều chi tiết/ khía cạnh khác nhau, nhờ vào các thuật toán mô phỏng hệ thần kinh người và thực hiện việc “learning” từ lượng dữ liệu lớn được cung cấp để giải quyết những vấn đề cụ thể.

Tương tự với Machine Learning, Deep Learning cũng tự rút ra những bài học/kinh nghiệm từ những sự việc cụ thể. Thuật toán Deep learning thực hiện một nhiệm vụ nhiều lần, sau mỗi lần thực hiện, nó sẽ tự điều chỉnh cách thức thực hiện nhiệm vụ từng chút một, qua đó cải thiện kết quả được tốt hơn.

Ranh giới mong manh giữa NGƯỜI và MÁY (AI, ML, DL và NN)

Deep Learning cho phép kết nối dữ liệu giữa tất cả các tế bào thần kinh nhân tạo, rồi điều chỉnh chúng theo dữ liệu mẫu được đưa vào.

Số lượng “tế bào thần kinh nhân tạo” được thêm vào càng nhiều => kích thước của dữ liệu sẽ càng lớn => AI có thể học tập ở nhiều cấp độ trừu tượng hơn.

Nhờ vậy mà chúng ta có thể xây dựng được một hệ thống “learning” phức tạp hơn, mà không phụ thuộc vào bất kỳ một thuật toán cụ thể nào !

Sau đây là một số ứng dụng phổ biến của Deep Learning hiện nay:

Đầu tiên là ứng dụng Deep Learning vào hệ thống gợi ý, các nền tảng Thương mại điện tử lớn hiện nay như Shopee, Tiki, SenDo,… đều có hệ thống gợi ý chính xác, từ đó tăng mức độ tương tác với người dùng, giúp người dùng tìm ra những sản phẩm ưng ý nhất.

Ranh giới mong manh giữa NGƯỜI và MÁY (AI, ML, DL và NN)

Cụ thể là chúng dựa trên các dữ liệu của người dùng tìm kiếm và tương tác trên các thiết bị có kết nối Internet để gợi ý thêm những sản phẩm họ sẽ thích (như trên các nền tảng mua sắm), gợi ý các bài quảng cáo/được tài trợ (như trên Google) hoặc các khóa học mà người học quan tâm (như trên các nền tảng học online: Edumall, Topica, Unica…).

Tiếp đến là việc ứng dụng Deep Learning vào ứng dụng Nhận diện hình ảnh, mục tiêu của công nghệ nhận diện ảnh là nhận biết và xác định các đối tượng trong ảnh cũng như hiểu được nội dung và ngữ cảnh trong đó.

Ví dụ như chương trình nhận diện của kỹ sư công nghệ AI: Adam Geitgey với khả năng phân biệt hai khuôn mặt tương tự nhau: nam diễn viên Will Ferrell và nghệ sĩ rock Chad Smith, theo thời gian thực.

Công nghệ nhận diện khuôn mặt không còn xa lạ gì với người dùng Facebook nữa rồi, nó dùng để gợi ý tag tên bạn bè khi đăng ảnh, hay là ứng dụng vào khoa học tội phạm để điều tra phá án thông qua các hệ thông camera an ninh công cộng…

Ứng dụng Deep Learning vào trong y khoa: Watson của IBM đã phát hiện ra một loại bệnh mà các bác sĩ đã phải bó tay vì không thể tìm ra ở một nữ bệnh nhân.

Ông đã sử dụng công nghệ để so sánh bộ gen của người phụ nữ này với hơn 20 triệu kết quả nghiên cứu bệnh khác. Chỉ trong 10 phút, Watson đã đưa ra kết quả, nó là một chứng Leukemia cực kỳ hiếm gặp.

Ngoài ra, Deep Learning còn được ứng dụng rất nhiều trong thực tế nữa. Công nghệ ngày càng phát triển thì Deep Learning sẽ còn được cải tiến hơn nữa qua năm tháng, chúng ta hãy cùng chờ đón thêm những ứng dụng tuyệt vời của nó nhé.

#4. Tổng kết

Tuy có rất nhiều ưu điểm vượt trội nhưng ở thời điểm hiện tại, nhưng Deep Learning – DL (dạng AI mà nhân loại đang theo đuổi) cũng có những giới hạn nhất định.

Thứ nhất là nó luôn đòi hỏi một lượng dữ liệu đầu vào khổng lồ để máy tính học hỏi, quy trình mất nhiều thời gian và sức mạnh xử lý vốn chỉ dành cho các máy server khủng mới có thể làm được.

Khi không có đủ dữ liệu đầu vào, hoặc nếu có đủ dữ liệu đầu vào nhưng lại không có đủ sức mạnh phần cứng để xử lý thì kết quả cuối cùng mà máy tính đưa ra cũng không chính xác.

Thứ hai nữa là, DL chưa thể nhận biết được những thứ phức tạp hay tương tự nhau vì hiện nay chưa có kĩ thuật nào đủ tốt để AI có thể rút ra những kết luận đó một cách logic, bởi vì khả năng nhận biết như con người không thể đạt được trong một sớm một chiều được.

Không thể phủ nhận là trí tuệ con người đang phát triển với tốc độ chưa từng có, nay với sự trợ giúp của AI nữa thì những thứ mà con người có thể làm ra được trong tương lai chắc bạn và tôi sẽ không thể tưởng tượng ra nổi.

Có chăng những bộ phim khoa học viễn tưởng về chủ đề này mới chỉ khắc họa một phần của thế giới ấy, hãy xem Westworld của HBO để thấy nhân vật Dolores chính là một hiện thân của Artificial Super Intelligence (ASI) – dạng trí tuệ nhân tạo cao cấp mà con người có thể mường tượng ra.

AI đem đến rất nhiều giá trị cho nhân loại, và cũng tiềm ẩn cả những nguy cơ nữa, nhiều chuyên gia lo lắng rằng, khi AI đạt tới một mốc tiến hóa nào đó thì đó cũng là thời điểm loài người diệt vong.

Và thật là hợp lý khi AI vẫn còn sơ khai mà người ta đã phải áp đặt ra nhiều luật lệ trong xây dựng các sản phẩm AI có đạo đức (như kiểu: thứ nhất, con người luôn đúng; thứ hai, nếu con người sai, xem lại điều một vậy).

Dự báo cho rằng, từ 10 đến 30 năm nữa ngành khoa học này sẽ phát triển lên tới đỉnh cao, vậy nên, bạn và tôi hãy gắng kiếm thật nhiều tiền và sức khỏe để luôn sẵn sàng trải nghiệm những thứ tuyệt vời mà AI mang lại nhé ᵔᴥᵔ

CTV: Dương Minh Thắng – Bài viết gốc tại blogchiasekienthuc.com

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

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