Cách tư duy lập trình giúp công việc bạn nhanh hơn

seminoon seminoon @seminoon

Cách tư duy lập trình giúp công việc bạn nhanh hơn

19/04/2015 01:08 PM
391

Học lập trình không phải là chuyện mà ta có thể làm trong một sớm, một chiều, nhưng nó không phải là quá khó khăn. Có rất nhiều điều bạn có thể làm cho nó dễ dàng hơn khi bạn học lập trình. Bài viết sau đây  sẽ có thể giúp ích cho chúng ta khám phá được những bí quyết để học lập trình tốt hơn và nhanh hơn.




5 cách để học lập trình nhanh hơn

Một trong những chủ đề được nói đến rất nhiều về mẹo học lập trình là:

Đừng đi quá nhanh, hãy nắm bắt nó trước khi đi tiếp. (Don’t go too fast, get it right before move on)

Chúng ta thường thắc mắc tại sao trong lớp học của mình, có một số bạn của chúng ta biết trước về một số ngôn ngữ lập trình. Trong những tuần đầu tiên học thường nắm bắt kiến thức rất nhanh, nhưng càng về sau họ lại bị bỏ ở đằng sau bởi những sinh viên khác. Tại sao họ lại bị bỏ xa trong khi nền tảng của họ tốt hơn.???

Đó chính là việc họ đã đi quá nhanh, và lối mòn của họ là tưởng rằng mình biết tất cả nhưng thực sự họ hiếm khi thực hiện công việc lập trình. Có thể họ biết một số cái nâng cao hơn so với những sinh viên foundationkhác, nhưng bấy nhiêu đó là


















không đủ để nắm vững các nguyên tắc cơ bản. Cũng giống như khi chúng ta làm bài kiểm tra môn toán thường có 8 điểm là có một người có học lực khá có thể đạt được, nhưng có một số sinh viên làm được bài 2 điểm khó kia và có một số bài tập cơ bản vẫn chưa hoàn thành, nên kết quả không bằng một sinh viên nắm vững các kiến thức cơ bản có thể làm được.

Do đó, trước tiên chúng ta cần tạo cho mình một nền tản (Foundation) tốt bằng cách thường xuyên luyện tập thực hành cái bài tập lập trình. Trong quá trình luyện tập như vậy bạn sẽ thấy được những vấn đề cơ bản mà các lập trình viên thường mắc phải. Và tạo cho mình một thoái quen tốt để giải quyết vấn đề.

Đồng thời bạn đừng bao giờ ngừng tiến trình luyện tập của mình, cũng không nên đi quá nhanh hay quá chậm. Đừng tránh một chủ đề nào sau khi bạn đã nắm vững tất cả những gì dẫn đến nó. Bằng cách đối mặc với nhiều ý tưởng và thách thức, bạn sẽ có một chất men giúp bạn nhanh chóng nắm bắt được những vấn đề cơ bản. Sau đây là 5 cách để bạn định hướng được việc học lập trình nhanh hơn.

1. Xem các code ví dụ (Look at the Example Code):

- Khi đọc sách chúng ta thường đọc các từ trên trang sách đó, nhưng học lập trình thì đó là code. Khi bạn mới bắt đầu học lập trình, bạn nên xem xét kỹ lưỡng và cố gắng hiểu từng ví dụ. Trước khi đọc các lời giải thích về chương trình trong

sách, bạn nên cố gắng đọc và hiểu các đoạn code màread code tác giả đã viết dùng để làm gì. Tuy các ví dụ đó không phải khi nào đánh vào máy cũng chạy, nhưng nó tập cho chúng ta một thoái quen xem code cẩn thận và góp phần giúp chúng ta viết code rõ ràng hơn.












- Chúng ta phải viết code làm sao để cho các lập trình viên khác có thể đọc và hiểu nó, và để khi chính mình nhìn lại cũng nắm được. Do đó cần phải tuân thủ những nguyên tắc, và cú pháp khi viết code để đảm bảo kiểm tra lỗi đơn giản hơn, các phần hướng dẫn viết code theo một mẫu chuẩn thường được viết ở đầu các cuốn sách lập trình, nhưng ít người học lập trình để ý đến vấn đề này.

2. Đừng chỉ đọc các code ví dụ -  hãy chạy thử nó (Don’t just Read exam code – Run It)

- Khi bạn đọc một chương trình hướng dẫn (hay một cuốn sách), bạn thường xem các code ví dụ của nó và nói “Tôi đã nắm được nó, tôi đã hiểu được nó….”. Tất nhiên là bạn có thể nắm được nó, nhưng bạn thực sự chưa hiểu được nó hoạt động như thế nào, cho kết quả ra sao.

Do đó trước khi đọc một cuốn sách về lập trình, bạn nên cài trình biên dịch của ngôn ngữ mà bạn đang học vào máy (ví dụ học C++ thì bạn cài Dev C++ hay visual c++). Để sẵn sàng chạy thử tất cả các ví dụ trong cuốn sách hay chương trình mà bạn đang đọc.

- Tôi nói chạy thử ở đây không phải là copy rồi paste vào rồi nhấn F5. Tôi khuyên bạn nên tự mình đánh những đoạn code đó vào chương trình biên dịch, vì khi đó bạn thực sự buộc mình phải đi qua tất cả các mã,việc gõ mã lệnh sẽ giúp bạn chú ý đến các chi tiết cú pháp của ngôn ngữ – những sự thiếu soát buồn cười như thiếu đấu chấm phẩy ở cuối mỗi câu lệnh có thể làm bạn hết sức đâu đầu.

- Sau khi gõ mã lệnh vào chương trình, hãy chạy thử nó. Rồi viết thêm một số câu lệnh mới vào chương trình của mình xem nó có hoạt động xem. Điều đó sẽ giúp bạn hiểu nhanh hơn mỗi câu lệnh có ý nghĩa như thế nào.

3. Hãy viết mã riêng của bạn  càng sớm càng tốt (Write your own code as soon as possible).

- Khi bắt đầu viết một chương trình bạn không biết phải bắt đầu từ đâu, sử dụng cấu trúc dữ liệu gì? Việc phân bổ viết code như thế nào? Xử lý các phương thức ra sao?… Điều đầu tiên là bạn sử dụng các công cụ tìm kiếm ở google hoặc các công cụ tìm kiếm khác để tìm kiếm đoạn mã mình cần. Đây là một điều có thể làm cho tư duy lập trình của bạn ngày càng giảm đi và ngày càng bị lệ thuộc vào các công cụ tìm kiếm.


 

write
















- Giải pháp được đưa ra trong trường hợp này là bạn hãy tự nghĩ cho mình một thuật toán riêng. Đầu tiên bạn viết nó bằng mã giả, sau đó dùng ngôn ngữ lập trình để viết lại. Tuy việc này rất khó và tốn nhiều thời gian, nhưng nó sẽ giúp bạn có được những kinh nghiệm thực sự hữu ích, khả năng tư duy lập trình ngày càng phát triển. Thay vì lên mạng tìm code về sửa.

- Trường hợp ý tưởng chương trình của bạn lớn, phải viết một lượng lớn code. Khi đó bạn hãy phân nhỏ từng tính năng chương trình của mình ra, tự tập thiết kế cấu trúc của chương trình nhỏ đó, rồi ghép chúng lại với nhau sẽ được một chương trình lớn hoàn chỉnh hơn. Có thể chương trình đó không hoạt động tốt, nhưng cái mà bạn được ở đây chính là kinh nghiệm và một tư duy tự lập trong lập trình.

4.  Tìm hiểu cách sử dụng một công cụ Debug (Learn to use a Debugger)

- Debug là một công cụ rất tốt dùng để gỡ rối chương trình của bạn khi có một lỗi nào đó là chương trình bạn chạy sai. Nó cho bạn theo dõi giá trị của các biến và các thay đổi của chúng qua từng mã lệnh của chương trình. Công cụ debug mạnh nhất có lẽ được tích hợp trong các sản phẩm của Microsoft như Visual Studio (Hiện nay là visual studio 2010). Công cụ debug giúp chúng ta hiểu chương trình của mình hơn, và là thứ chúng ta cần phải biết khi viết chương trình.

-  Một chương trình debug có thể giúp bạn nhanh chóng trả lời những gì mà bạn đang làm như ví dụ bên dưới.

int main() { int x; int y; if( x > 4 ) // <— Giá trị của X ở đây là bao nhiêu? { y = 5; // <— Dòng code này thực thi như thế nào? } }

- Và lời khuyên cuối cùng về debug là: khi bạn lần đầu tìm hiểu về debuger, có thể nó sẽ làm bạn mất khá nhiều thời gian khi bạn sửa lỗi chương trình của mình. Nhưng khi bạn nắm được các kiến thức về debug nó sẽ đem lại cho bạn một lợi ích lớn trong việc tiết kiệm thời gian khi sửa lỗi chương trìdebugsnh.






















. Tôi tin rằng mỗi bạn đều có thể tìm ra cho mình một cách debug chương trình hiệu quả, bởi nó sẽ theo suốt sự nghiệp lập trình của bạn.


- Tôi thường thấy các sinh viên khác không muốn sử dụng công cụ debug (có thể là không biết giống như tôi lúc trước). Những sinh viên đã tự làm khó mình trong việc tìm kiếm lỗi sai trong chương trình. Do đó khi bạn đã xác định theo con đường lập trình, hãy học cách sử dụng một công cụ debug, nó sẽ mang lại cho bạn nhiều lợi ích thiết thực hơn bạn nghĩ.

5. Tìm kiếm thêm những nguồn tài tài liệu khác (Seek our more sources)

- Khi bạn không hiểu một điều gì đó, internet là một nơi với lượng thông tin khổng lồ mà bạn tìm đến. Thế nhưng có những bài viết về đề tài mà bạn muốn tìm thì lại được tác giả viết sơ sài, hoặc có thể sai. Do đó bạn phải hết sức thận trọng khi sử dụng các thông tin từ internet vào chương trình của mình.

- Ngoài ra việc tìm kiếm một cuốn sách với những giải thích chi tiết sẽ giúp bạn nhanh chóng nắm được vấn đề hơn. 

- Bạn cũng có thể tham gia vào các diễn đàn về lập trình (ví dụ lập trình c, c++, c# thì có diễn đàn Congdongcviet.com), khi không hiểu một vấn đề gì đó bạn có thể post bài để các thành viên trong diễn đàn giúp đỡ cho bạn. Nếu có khả năng về tiến anh thì bạn lên các diễn đàn nước ngoài sẽ có nhiều thành viên xuất sắc ở đó tìm kiếm thông tin và trả lời giúp (codeproject.com, cprogramming.com, cplusplus.com…). Lưu ý khi hỏi trên các diễn đàn bạn phải đặt câu hỏi ngắn gọn, tập trung vào mô tả nội dung vấn đề mà bạn đang gặp vướng mắc thì bạn sẽ nhận được câu trả lời tốt hơn.

- Việc trước mỗi buổi học nên chuẩn bị một danh sách các câu hỏi về những vướng mắc mà bạn gặp phải vào một cuốn sổ tay nhỏ để lên hỏi giáo viên hoặc bạn bè là một việc rất có ích, nó sẽ giúp bạn tiếp thu hơn, và nó cho thấy rằng bạn là một con người cầu tiến, ham học hỏi.

- Cuối cùng là việc hết sức quan trọng, Học Nhóm. Học nhóm sẽ giúp bạn tiến bộ nhanh hơn, tăng cường khả năng giao tiếp với bạn bè và đồng nghiệp sau này. Khi làm việc nhóm bạn sẽ viết ra được những chương trình lớn hơn và có sức thuyết phục người dùng hơn. Tôi khuyên bạn đừng bao giờ ôm hết công việc về mình.

Tư duy về lập trình hàm: Suy nghĩ theo lập trình hàm,

Tóm tắt:  Neal Ford, tác giả của loạt bài Tư duy về lập trình hàm tiếp tục chuyến du lịch có hướng dẫn của ông về các cấu kiện và các mẫu hình lập trình hàm. Bạn sẽ xem xét mã phân loại số trong Scala và xem qua việc kiểm tra đơn vị trong thế giới lập trình hàm. Sau đó, bạn sẽ tìm hiểu về áp dụng một phần (partial application) và currying là kỹ thuật chuyển đổi một hàm, lấy nhiều đối số (hoặc n đối số) theo một cách sao cho có thể gọi hàm đó như là một chuỗi các hàm, mỗi hàm có một đối số (áp dụng một phần) — hai cách tiếp cận hàm tạo điều kiện thuận lơi cho việc sử dụng lại mã — và sẽ thấy phép đệ quy phù hợp với cách tư duy về lập trình hàm như thế nào.

Loạt bài này nhằm mục đích định hướng lại cách nhìn của bạn đối với tư duy về lập trình hàm, giúp bạn xem xét các vấn đề chung theo các cách mới và tìm mọi cách để cải tiến việc viết mã hàng ngày của bạn. Loạt bài này khám phá các khái niệm, các khung công tác lập trình hàm, cho phép lập trình hàm trong phạm vi ngôn ngữ Java, các ngôn ngữ lập trình hàm chạy trên JVM và một số khuynh hướng phát triển trong tương lai của thiết kế ngôn ngữ lập trình. Loạt bài này được nhằm đến các nhà phát triển Java, những người biết về Java và cách hoạt động trừu tượng của nó nhưng có rất ít hoặc chưa có chút kinh nghiệm nào về sử dụng một ngôn ngữ lập trình hàm.

Trong các bài đăng đầu tiên và thứ hai của loạt bài Tư duy về lập trình hàm, tôi xem xét một số chủ đề về lập trình hàm và chúng liên quan đến Java™ và các ngôn ngữ liên quan của nó như thế nào. Bài đăng này tiếp tục hướng nghiên cứu này, cho thấy một phiên bản Scala của trình phân loại số từ các bài đăng trước và thảo luận về một số chủ đề nhuốm màu-học thuật như currying, áp dụng một phần (partial) và phép đệ quy.

Trình phân loại số trong Scala

Tôi đã dành lại một phiên bản trình phân loại số bằng Scala đến phút cuối vì nó là một phiên bản có ít bí ẩn cú pháp nhất, ít nhất là với các nhà phát triển Java. (Nhắc lại các yêu cầu của trình phân loại số: Cho số nguyên dương bất kỳ lớn hơn 1 nào, bạn phải phân loại nó là perfect (hoàn hảo), abundant (dư thừa) hay deficient (thiếu hụt). Một số hoàn hảo là một số mà các thừa số, không bao gồm chính số đó, cộng lại thì bằng chính số đó. Tổng các thừa số của số dư thừa sẽ lớn hơn số đó và tổng các thừa số của số thiếu hụt sẽ nhỏ hơn số đó). Liệt kê 1 cho thấy phiên bản Scala:


Liệt kê 1. Trình phân loại số trong Scala
        
package com.nealford.conf.ft.numberclassifier object NumberClassifier {
   def isFactor(number: Int, potentialFactor: Int) = number % potentialFactor == 0 
   def factors(number: Int) = (1 to number) filter (number % _ == 0) 
   def sum(factors: Seq[Int]) = factors.foldLeft(0)(_ + _) 
   def isPerfect(number: Int) = sum(factors(number)) - number == number 
   def isAbundant(number: Int) = sum(factors(number)) - number > number 
   def isDeficient(number: Int) = sum(factors(number)) - number < number } 

Thậm chí nếu bạn chưa bao giờ nhìn thấy Scala cho đến nay, thì mã này vẫn hoàn toàn dễ đọc. Như trước đây, hai phương thức đáng quan tâm là factors()sum(). Phương thức factors() lấy danh sách các số từ 1 đến số đích và áp dụng phương thức filter() dựng sẵn của Scala, sử dụng khối mã ở phía bên phải làm tiêu chuẩn lọc (cũng được gọi là một vị từ). Khối mã này lợi dụng tham số ngầm, của Scala, cho phép ký hiệu giữ chỗ không tên (ký tự _) khi không cần một biến có tên. Nhờ sự linh hoạt cú pháp của Scala, bạn có thể gọi phương thức filter() giống như cách bạn gọi một toán tử. Nếu bạn thích, có thể viết, (1 to number).filter((number % _ == 0)) cũng được.

Phương thức sum() sử dụng phép toán fold left bây giờ đã thành quen thuộc (trong Scala, phép toán này được triển khai thực hiện dưới dạng phương thức foldLeft()). Tôi không cần đặt tên cho các biến trong trường hợp này, vì vậy tôi sử dụng ký tự _ như là một ký hiệu giữ chỗ, lợi dụng cú pháp sạch, đơn giản để định nghĩa một khối mã. Phương thức foldLeft() thực hiện nhiệm vụ giống như phương thức có tên tương tự trong thư viện Functional Java (xem Tài nguyên), đã xuất hiện trong bài đăng đầu tiên:

  1. Lấy một giá trị ban đầu và kết hợp nó qua một phép toán với phần tử đầu tiên của danh sách.
  2. Lấy kết quả và áp dụng phép toán tương tự cho phần tử tiếp theo.
  3. Tiếp tục làm việc này cho đến khi danh sách được khai thác hết.

Đây là một phiên bản tổng quát về cách áp dụng một phép toán ví dụ như cộng một danh sách các số: bắt đầu với số không, cộng vào phần tử đầu tiên, lấy kết quả đó và cộng nó với phần tử thứ hai và tiếp tục cho đến khi danh sách được dùng hết.

Kiểm tra đơn vị

Mặc dù tôi đã không thể hiện các bài kiểm tra đơn vị đối với các phiên bản trước, tất cả các ví dụ đều có các bài kiểm tra. Một thư viện kiểm tra đơn vị hiệu quả tên là ScalaTest hiện có sẵn cho Scala (xem Tài nguyên). Liệt kê 2 cho thấy bài kiểm tra đầu tiên mà tôi đã viết để kiểm tra lại phương thức isPerfect() của Liệt kê 1:


Liệt kê 2. Một bài kiểm tra đơn vị cho trình phân loại số của Scala
        
@Test def negative_perfection() { 
   for (i <- 1 until 10000) 
      if (Set(6, 28, 496, 8128).contains(i))
         assertTrue(NumberClassifier.isPerfect(i)) 
      else assertFalse(NumberClassifier.isPerfect(i)) 
} 

Nhưng cũng giống như bạn, tôi đang cố gắng để học cách suy nghĩ theo lập trình hàm nhiều hơn và mã trong Liệt kê 2 đã làm phiền tôi theo hai cách. Đầu tiên, nó dùng vòng lặp để làm một cái gì đó, trưng ra rõ ràng suy nghĩ mệnh lệnh. Thứ hai, tôi không quan tâm đến cái bẫy nhị phân của các câu lệnh if. Vấn đề tôi đang cố gắng giải quyết là gì? Tôi cần phải đảm bảo rằng trình phân loại số của tôi không xác định nhầm một số không tròn số là tròn số. Liệt kê 3 cho thấy giải pháp cho vấn đề này, sau khi đã phát biểu hơi khác đi:


Liệt kê 3. Bài kiểm tra khác để phân loại số tròn số
        
@Test def alternate_perfection() { 
   assertEquals(List(6, 28, 496, 8128), (1 until 10000) 
   filter (NumberClassifier.isPerfect(_))) } 

Liệt kê 3 xác nhận rằng các số tròn số duy nhất trong khoảng từ 1 đến 10.000, chỉ là những số có trong danh sách số tròn số đã biết. Suy nghĩ theo lập trình hàm mở rộng không chỉ với mã của bạn, mà còn với cách bạn suy nghĩ về việc kiểm tra nó nữa.

Về đầu trang

Áp dụng một phần và currying

Cách tiếp cận lập trình hàm mà tôi đã cho thấy để lọc các danh sách là phổ biến trong các ngôn ngữ và các thư viện lập trình hàm. Việc sử dụng khả năng chuyển giao mã lệnh như là tham số (như với phương thức filter() trong Liệt kê 3) minh họa cho cách suy nghĩ về sử dụng lại mã theo một cách khác. Nếu bạn đến từ một thế giới hướng đối tượng dựa vào-các mẫu-thiết kế truyền thống, hãy so sánh cách tiếp cận này với mẫu thiết kế Phương thức khuôn mẫu (Template Method) từ cuốn sách Các mẫu thiết kế của Bộ tứ (xem Tài nguyên). Các mẫu Phương thức khuôn mẫu xác định bộ khung của một thuật toán trong một lớp cơ sở, sử dụng các phương thức trừu tượng và cách viết đè để trì hoãn các chi tiết riêng cho các lớp con. Khi sử dụng hàm hợp (composition), cách tiếp cận lập trình hàm cho phép bạn chuyển giao theo cách lập trình hàm cho các phương thức để chúng áp dụng chức năng đó theo cách thích hợp.

Một cách khác để đạt được việc sử dụng lại mã là qua currying. Được đặt tên phỏng theo tên nhà toán học Haskell Curry (ngôn ngữ lập trình Haskell cũng được đặt tên theo tên nhà toán học đó), currying biến đổi một hàm nhiều đối số sao cho nó có thể được gọi như là một chuỗi các hàm chỉ có một đối số. Liên quan chặt chẽ với nó là áp dụng một phần, một kỹ thuật để gán một giá trị cố định cho một hoặc nhiều đối số của một hàm, vì thế tạo ra một hàm khác có arity (số các tham số của hàm đó) nhỏ hơn. Để hiểu rõ sự khác biệt này, hãy bắt đầu bằng cách xem xét mã Groovy trong Liệt kê 4, minh họa currying:


Liệt kê 4. Currying trong Groovy
        
def product = { x, y -> return x * y } 
def quadrate = product.curry(4) 
def octate = product.curry(8) 
println "4x4: ${quadrate.call(4)}" 
println "5x8: ${octate(5)}" 

Trong Liệt kê 4, tôi định nghĩa product là một khối mã chấp nhận hai tham số. Khi sử dụng phương thức curry() dựng sẵn của Groovy, tôi sử dụng product như là khối xây dựng cho hai khối mã mới: quadrate (gấp bốn) và octate (gấp tám). công khai một phương thức call() hoặc sử dụng vỏ cú pháp mức-ngôn ngữ đã được cung cấp bằng cách viết các cặp dấu ngoặc đơn có chứa bất kỳ các tham số nào sau tên khối-mã (ví dụ như là octate(5)).

Áp dụng một phần là một kỹ thuật rộng hơn, tương tự như currying nhưng không chỉ hạn chế hàm kết quả cho một đối số duy nhất. Groovy sử dụng phương thức curry() để xử lý cả hai currying và áp dụng một phần, như trong Liệt kê 5:


Liệt kê 5. Áp dụng một phần so với currying, cả hai đều sử dụng phương thức curry() của Groovy
        
def volume = { h, w, l -> return h * w * l } 
def area = volume.curry(1) 
def lengthPA = volume.curry(1, 1) //partial application 
def lengthC = volume.curry(1).curry(1) // currying 
println "The volume of the 2x3x4 rectangular solid is ${volume(2, 3, 4)}" 
println "The area of the 3x4 rectangle is ${area(3, 4)}" 
println "The length of the 6 line is ${lengthPA(6)}" 
println "The length of the 6 line via curried function is ${lengthC(6)}" 

Khối mã volume trong Liệt kê 5 tính thể tích khối của khối chữ nhật ba chiều bằng cách sử dụng công thức đã biết. Sau đó tôi tạo ra một khối mã area (tính diện tích của hình chữ nhật) bằng cách đặt kích thước đầu tiên của volume (chiều caoh) là 1. Để sử dụng volume như là một khối xây dựng cho một khối mã trả về độ dài của một đoạn thẳng, tôi có thể thực hiện hoặc áp dụng một phần hoặc currying. lengthPA dùng áp dụng một phần bằng cách đặt từng tham số trong hai tham số đầu tiên là 1. lengthC dùng currying hai lần để sinh ra cùng kết quả. Khó thấy được sự khác biệt và kết quả cuối cùng là giống nhau, nhưng nếu bạn sử dụng các thuật ngữ curryingáp dụng một phần lẫn lộn thay thế cho nhau trong tầm nghe của một người lập trình hàm, bạn có thể bị chỉnh sửa lại đấy.

Lập trình hàm cung cấp cho bạn các khối xây dựng mới, khác nhau để đạt được cùng các mục tiêu như các ngôn ngữ mệnh lệnh thực hiện bằng các cơ chế khác. Các mối quan hệ giữa những khối xây dựng này phải được suy nghĩ cẩn thận. Ở trên, tôi đã cho thấy hàm hợp là một cơ chế sử dụng lại mã. Bạn đừng ngạc nhiên khi bạn có thể kết hợp currying và hàm hợp. Hãy xem xét mã Groovy trong Liệt kê 6:


Liệt kê 6. Hàm hợp áp dụng một phần
        
def composite = { f, g, x -> return f(g(x)) } 
def thirtyTwoer = composite.curry(quadrate, octate) 
println "composition of curried functions yields ${thirtyTwoer(2)}" 

Trong Liệt kê 6, tôi tạo ra khối mã composite là hàm hợp của hai hàm. Sử dụng khối mã đó, tôi tạo ra khối mã thirtyTwoer, dùng áp dụng một phần để kết hợp hai phương thức với nhau.

Bằng cách dùng áp dụng một phần và currying, bạn đạt được các mục tiêu tương tự với các cơ chế như của mẫu thiết kế Phương thức khuôn mẫu. Ví dụ, bạn có thể tạo ra một khối mã incrementer bằng cách xây dựng nó trên đỉnh một khối mã adder, như trong Liệt kê 7:


Liệt kê 7. Các khối xây dựng khác nhau
        
def adder = { x, y -> return x + y } 
def incrementer = adder.curry(1)
println "increment 7: ${incrementer(7)}" 

Tất nhiên, Scala hỗ trợ currying, như được minh họa bằng đoạn mã (snippet) lấy từ tài liệu Scala được hiển thị trong Liệt kê 8:


Liệt kê 8. Currying trong Scala
        
object CurryTest extends Application { 
   def filter(xs: List[Int], p: Int => Boolean):
        List[Int] = if (xs.isEmpty) xs 
                    else if (p(xs.head)) xs.head :: filter(xs.tail, p) 
                         else filter(xs.tail, p) 
   def dividesBy(n: Int)(x: Int) = ((x % n) == 0) 
   val nums = List(1, 2, 3, 4, 5, 6, 7, 8) 
   println(filter(nums, dividesBy(2))) 
   println(filter(nums, dividesBy(3))) 
} 

Mã trong Liệt kê 8 cho thấy cách thực hiện một phương thức dividesBy() được phương thức filter() sử dụng. Tôi chuyển một hàm vô danh tới phương thức filter() sử dụng. Tôi chuyển một hàm vô danh tới phương thức dividesBy() bằng giá trị được sử dụng để tạo khối mã. Khi tôi chuyển giao khối mã được tạo ra bằng cách truyền số đích của tôi như một tham số, Scala tạo ra một hàm mới bằng currying.

Về đầu trang

Lọc qua phép đệ quy

Một chủ đề khác liên kết chặt chẽ với lập trình hàm là phép đệ quy, (theo Wikipedia) là "quá trình lặp lại các mục theo một cách tự đồng dạng". Trong thực tế, đó là một cách của khoa học máy tính để lặp lại qua hết mọi thứ bằng cách gọi một phương thức từ bên trong chính nó (luôn cẩn thận đảm bảo rằng bạn có một điều kiện thoát). Nhiều khi, phép đệ quy dẫn đến mã lệnh dễ hiểu bởi vì cốt lõi của vấn đề của bạn là cần làm điều tương tự lặp đi lặp lại xuống đến một danh sách giảm dần.

Hãy xem xét việc lọc một danh sách. Sử dụng một cách tiếp cận vòng lặp, tôi chấp nhận một tiêu chuẩn lọc và lặp lại qua các nội dung, lọc ra các phần tử mà tôi không muốn. Liệt kê 9 cho thấy một cách thực hiện lọc đơn giản với Groovy:

Liệt kê 9. Lọc trong Groovy
        
def filter(list, criteria) { 
   def new_list = [] list.each { 
      i -> if (criteria(i)) new_list << i 
   } 
   return new_list 
} 
modBy2 = { n -> n % 2 == 0 } 
l = filter(1..20, modBy2)
println l 

Phương thức filter() trong Liệt kê 9 chấp nhận một list và một criteria (một khối mã chỉ rõ cách lọc danh sách ra sao) và lặp qua hết danh sách, thêm từng mục vào một danh sách mới nếu nó khớp với vị từ đó.

Bây giờ hãy xem lại Liệt kê 8, là một cách thực hiện bằng phép đệ quy chức năng lọc trong Scala. Nó làm theo một mẫu phổ biến trong các ngôn ngữ lập trình hàm để xử lý một danh sách. Một khung nhìn của một danh sách gồm hai phần: mục ở đầu danh sách (mục đầu) và tất cả các mục khác còn lại. Nhiều ngôn ngữ lập trình hàm có các phương thức cụ thể để lặp qua hết một danh sách bằng cách sử dụng cách biểu diễn này. Trước tiên phương thức filter() kiểm tra xem danh sách có rỗng không — điều kiện thoát quan trọng cốt yếu cho phương thức này. Nếu danh sách rỗng, chỉ cần trả về. Nếu trái lại, sử dụng điều kiện vị từ (p) được chuyển giao như là một tham số. Nếu điều kiện này đúng (có nghĩa là tôi muốn có mục này trong danh sách của mình), tôi trả về một danh sách mới được xây dựng bằng cách lấy mục đầu hiện tại và phần còn lại được lọc của danh sách. Nếu điều kiện vị từ sai, tôi trả về một danh sách mới chỉ chứa đúng phần còn lại được lọc (loại bỏ phần tử đầu tiên). Các toán tử xây dựng danh sách trong Scala làm cho các điều kiện trả về cho cả hai trường hợp hoàn toàn dễ đọc và dễ hiểu.

Tôi đoán là bây giờ bạn chưa sử dụng phép đệ quy tí nào — nó thậm chí không phải là một phần của hộp công cụ của bạn. Tuy nhiên, một phần lý do nằm ở thực tế là hầu hết các ngôn ngữ lập trình mệnh lệnh hỗ trợ nó mờ nhạt, làm cho việc sử dụng khó khăn hơn là đáng ra nên có. Bằng cách thêm cú pháp sạch và sự hỗ trợ, các ngôn ngữ lập trình hàm làm cho phép đệ quy trở thành một ứng cử viên để sử dụng lại mã đơn giản.


Bài đăng này hoàn tất nghiên cứu của tôi về các đặc tính trong thế giới tư duy lập trình hàm. Thật trùng hợp, phần lớn bài viết này đã nói về việc lọc, cho thấy nhiều cách để sử dụng nó và thực hiện nó. Nhưng điều này không quá bất ngờ. Nhiều mẫu hình lập trình hàm được xây dựng xung quanh các danh sách vì phần lớn việc lập trình rốt cuộc là xử lý các danh sách về mọi thứ. Rất có ý nghĩa khi tạo ra các ngôn ngữ và các khung công tác nạp thêm các tiện ích cho các danh sách.

Trong bài đăng tiếp theo, tôi sẽ nói sâu về một trong các khối xây dựng của lập trình hàm: tính bất biến.


MỜI BẠN THAM KHẢO THÊM:

Cách học code hiệu quả

Thực ra tiêu đề của bài viết cũng không thực sự chính xác với nội dung của bài, nhưng tôi cũng chẳng biết đặt tiêu đề thế nào thì hợp lý hơn. Nhưng dài dòng chút thì là dưới đây là một số kinh nghiệm cá nhân của tôi trong quá trình học lập trình web. Tôi muốn chia sẻ với các bạn mới bắt đầu để các bạn rút ra được những bài học từ kinh nghiệm của tôi.

Nói trước rằng học cái gì cũng có nhiều phương pháp và mỗi người có một cách riêng để học. Nhưng như đã nói ở trên đây chỉ là kinh nghiệm của người đi trước nói ra xem bạn có thấy được điểm nào hữu dụng mà thôi. Tôi không cố gắng giáo điều cũng như không có ý cách của tôi là hiệu quả nhất mà chỉ có ý gợi mở những điều tôi cho là có lý.

Đừng copy và Paste code

Đây có lẽ là lời khuyên được nhiều người nói nhất và tôi cũng thấy rất đúng. Ban đầu khi mới làm quen với một ngôn ngữ lập trình nhìn mớ code như mớ bòng bong chấm phẩy tè le hết. Ngồi gõ lại thì lâu biết bao nhiêu, copy và paste cho nhanh. Nhưng chỉ bằng cách gõ lại bạn mới nhớ code hơn, nếu có gõ sai thì có cơ hội quay lại và chỉnh sửa lỗi của mình. Tuy video nào tôi cũng có source code để bạn tham khảo, nhưng bạn chỉ lấy đó làm mẫu thôi còn bạn vẫn phải tự gõ lại những gì bạn thấy trong video.

Vừa xem vừa làm

Bạn đừng có mở video lên, pha ly cà phê rồi ngồi vuốt râu khen “phải! phải!”. Cách đó tôi thấy không hiểu quả cho lắm. Trước đây tôi cũng từng ngồi khoanh tay gật gù khen có lý. Nhưng khi tắt video đi thì mình lại mơ hồ không rõ lắm. Chính vì thế bạn mở video một bên và cửa sổ code một bên. Xem đến đâu gõ đến đó thì hiệu quả hơn rất nhiều.

Tự làm sau khi xem

Đây có lẽ là cách tôi thấy hiệu quả nhất. Sau khi bạn xem video rồi, làm theo rồi, hiểu cách rồi. Hãy tắt video đi và tự làm lại từ đầu theo cách hiểu của mình. Sau đó tự sửa lỗi, tìm lỗi sai, khắc phục .v.v. nếu bế tắc thì mới xem lại video. Nếu bạn đã đào sâu suy nghĩ mà vẫn chưa ra cách, đến khi xem lại bạn sẽ nhớ lâu hơn rất nhiều.

 

coding

Code, code nữa, code mãi

Tôi không thể nhấn mạnh điểm này nhiều hơn nữa. Cách học code nhanh nhất là cứ bỏ mấy cuốn sách dầy cộm xuống. Mở trình soạn code lên và code. Sai thì sửa, quên thì xem lại, có lỗi tìm cách khắc phục, đào sâu suy nghĩ, google, đọc lại lý thuyết … nói chung tôi thấy cách hay nhất vẫn là tự tìm cách giải quyết trước khi hỏi. Bởi vì học lập trình là môn học cần tư duy độc lập và tìm tòi sáng tạo. Rất nhiều người khi mới bắt đầu gặp vấn đề hơi khó là phải hỏi đầu tiên mà không tự khám phá. Nếu cứ mãi hỏi như vậy bạn sẽ bị ì sức sáng tạo và tư duy không độc lập nữa.

Tự thêm thử thách

Đây là cách tôi rất hay tự làm với mình. Ví dụ bạn xem một tutorial về cách gửi mail bằng PHP trên izwebz. Trong video tôi có hướng dẫn gửi mail nhưng không gửi file đính kèm. Bạn hãy cho đấy là bài tập về nhà của mình và tự tìm cách khắc phục. Ví dụ khi tôi đọc một bài về jQuery Slider chẳng hạn, nếu người ta chỉ có chuyển hình kiểu chạy qua, tôi sẽ tự tìm cách tạo cho nó fade qua, vòng lại .v.v.. bằng cách tự tạo ra thách thức cho mình bạn sẽ tiến bộ mau hơn.

Học từ nhiều nguồn, nhiều tài liệu

Học làm web không như học phổ thông, không như làm toán cứ ráp công thức vô là giải được bài. Làm web mỗi người một cách làm, mỗi sách có những điểm hay điểm dở khác nhau, mỗi thầy giáo có chỗ mạnh chỗ yếu và mỗi trang web cũng có những điểm ưu điểm khuyết. Do vậy bạn nên tập hợp nhiều nguồn sách, video, ebook, trang web, tutorials v.v.. rồi đúc kết, chắt lọc ra cách mà bạn cho là tối ưu nhất. Tôi đôi khi hay kết hợp nhiều nguồn với nhau và tìm ra cách nào mình thấy dung hòa được tất cả các mặt.

Kết Luận

Như đã nói trên đây chỉ là kinh nghiệm cá nhân, bạn chỉ nên tham khảo và quan trọng hơn cả là tự tìm ra cách học phù hợp với bạn nhất. Nhưng nói ngắn gọn lại thì nếu đã xác định học lập trình, bạn phải tạo ra cho mình một thói quen tư duy độc lập. Chỉ hỏi khi thực sự hết cách, chỉ hỏi sau khi đã thử rất nhiều cách, chỉ hỏi khi đã suy nghĩ về vấn đề đó rất nhiều lần trong ngày và chỉ hỏi khi bạn thực sự không thể giải quyết được vấn đề.


Lập trình viên
Cách tự học lập trình hiệu quả nhất
Xử lý ảnh bằng Matlab đơn giản nhất
Cách lập kế hoạch cho công việc chuyên nghiệp và hiệu quả
Kinh nghiệm học thiết kế web
Cách lập kế hoạch phát triển bản thân hoàn hảo nhất
Cách lập kế hoạch cho bản thân tốt nhất



(ST)

Hỏi đáp, bình luận, trả bài:
*địa chỉ email của bạn được bảo mật

Hot nhất
Top xink
Bộ sưu tập
Chợ xink
Thanh lý