2013-04-01 47 views
8

(Tôi đang sử dụng từ "quy trình làm việc" - không theo ý nghĩa của quy trình công việc không đồng bộ - mà là theo ý nghĩa "luồng công việc", tức là cách bạn sử dụng nó như một phần của sự phát triển)F # Quy trình làm việc/Quy trình phát triển

Sau khi chơi với F # một thời gian, tôi đã bắt đầu phát triển ứng dụng F # đầu tiên của mình. Tôi đến từ C#/vb. Đã theo dõi các bản trình diễn/hội thảo khác nhau - đúng hay sai - tôi đã bắt đầu sử dụng fsi làm "công cụ" phát triển chính và làm việc trong lĩnh vực đó. Nếu tôi nhấn một vấn đề mà tôi cần phải gỡ lỗi, tôi có xu hướng phá vỡ hàm có vấn đề thành các bit nhỏ hơn và kiểm tra những công việc đó để thử và gỡ rối vấn đề.

Tuy nhiên, để giữ số lượng mã có thể quản lý được trong fsi, một khi tôi hài lòng với những gì tôi đã làm, tôi di chuyển nó vào tệp .fs và #load tệp .fs trở lại fsi. Khi ứng dụng trở nên lớn hơn, điều này có thể bắt đầu cảm thấy hơi khó khăn vì khi tôi cần refactor, tôi sẽ phải lấy lại nội dung từ tập tin fs thay đổi nó chạy công cụ để có được thứ gì đó hoạt động trở lại, trước khi đẩy mã trở lại vào tệp .fs. Hơn nữa phong cách này không thực sự là một phương pháp thử nghiệm đầu tiên và vì vậy tôi không nhận được lợi ích của việc xây dựng một bộ kiểm tra. (Tôi cũng có thể bỏ lỡ khả năng thiết lập các điểm ngắt/bước mã, istm trong các tình huống nhất định ví dụ đệ quy, có thể nhanh hơn để chẩn đoán lỗi hơn là phá vỡ các phần của một hàm - mặc dù điều này có sẵn trong VS11 và tôi không thiết lập phải) .. vì vậy tôi nghĩ rằng tôi có lẽ không làm những điều tối ưu hoặc không nghĩ về mọi thứ theo đúng cách.

Tôi đã tự hỏi liệu những người khác có thể cung cấp cách họ phát triển ứng dụng hay không. Bạn chủ yếu sử dụng fsi hay bạn bắt đầu với tdd. Nếu phương pháp tiếp cận tdd là phương tiện cơ bản chính và FSI sử dụng nhiều lựa chọn hơn để hỗ trợ trong việc thực hiện các thuật toán phức tạp hơn, thăm dò dữ liệu, v.v ...

Tôi đã xem xét this question và rõ ràng là nó trỏ đến các khung tdd khác nhau cho F #, nhưng tôi vẫn muốn tìm hiểu quy trình làm việc của các nhà phát triển F # dày dạn kinh nghiệm.

Nhiều thx

S

+0

Các bạn đã thử [file script] (http://blogs.msdn.com/b/carlnol/archive/2011/08/09/creating-f-fsx-script-files- from-fs-source-files.aspx? Redirected = true)? Dường như đây là cơ hội tốt để thêm một số thử nghiệm dọc theo cách –

+0

Thx. Bất kỳ cơ hội bạn có thể mở rộng trên đó một chút wrt để tdd? Tôi đã sử dụng chúng đơn giản như một cách "tự do" hơn để thực hiện các công cụ trong fsi. Tôi rõ ràng là thiếu một cái gì đó! –

+0

REPL không thay thế cho các thử nghiệm thích hợp. Họ khá bổ sung cho nhau. https://twitter.com/missingfaktor/status/314452078682595328 –

Trả lời

12

Tôi nghĩ rằng bạn đang đi đúng hướng.

Quá trình phát triển là vấn đề về hương vị. Tôi sẽ chia sẻ cách tiếp cận của tôi anyway.

  • Bắt đầu bằng một vài tệp fs. Mỗi tệp đại diện cho một mô-đun, bao gồm một nhóm các hàm liên quan chặt chẽ với nhau. Nó không phải chính xác ngay từ đầu; bạn thường di chuyển các chất liệu giữa các mô-đun.
  • Tạo một vài tệp fsx để kiểm tra nhanh khi bộ xương của mô-đun sẵn sàng.
  • Tạo dự án thử nghiệm và thiết lập gói NuGet. Tôi thường sử dụng NUnit và FsUnit cùng nhau.
  • Bất cứ khi nào fsx tạo kịch bản cho kết quả chính xác, hãy chuyển chúng đến các trường hợp kiểm tra. Thực hiện việc này lặp đi lặp lại.
  • Bao gồm Program.fs vào dự án chính và biên dịch thành tệp thực thi để gỡ lỗi nếu cần.

Nói chung, F # REPL là công cụ phát triển chính. Nó cho tôi phản hồi tức thời và cho phép thay đổi gia tăng, rất hữu ích trong việc tạo mẫu. Trong F #, TDD ít quan trọng hơn vì tỷ lệ lỗi thấp hơn nhiều so với các ngôn ngữ khác. Và tôi không kiểm tra mọi thứ, chỉ tập trung vào các chức năng chính và đảm bảo phạm vi kiểm tra cao.Sử dụng testdriven.net bổ trợ hoặc Visual Studio 2012 Premium and Ultimate có thể cung cấp cho bạn các thống kê hữu ích về phạm vi kiểm tra.

Sử dụng F # REPL và TDD, tôi gần như không bao giờ phải sử dụng gỡ lỗi. Bất cứ khi nào có hành vi sai, tôi dừng lại và suy nghĩ. Vì mã của bạn không có tác dụng phụ, bạn có thể dễ dàng giải thích chúng. Trong nhiều lần lý luận và một vài lệnh in có thể cho tôi câu trả lời đúng.

Bạn có thể sử dụng TDD trong F # REPL với UnquoteFsCheck. Các cựu cung cấp thử nghiệm thông qua báo giá, đó là khá ấn tượng. Sau này sử dụng cách tiếp cận thử nghiệm ngẫu nhiên mà là hấp dẫn trong việc xử lý các trường hợp góc của mã của bạn. Tôi thấy nó thực sự hữu ích khi các chương trình của bạn phải thỏa mãn các thuộc tính nhất định. Tuy nhiên, có thể mất thời gian để tìm hiểu cách sử dụng các khung công tác này một cách chính xác.

+0

Thx. Rất hữu ích. –

+0

@GuyCoder: Cảm ơn, chỉ cần thêm một câu về phạm vi mã. – pad

3

pad đưa ra một câu trả lời tuyệt vời rất thiết thực và hữu ích cho người mới sử dụng F #. Tôi sẽ đưa ra một phương tiện khác để những người khác không nghĩ rằng chỉ có một cách F # 'ers làm điều đó.

Lưu ý: Nếu bạn rất mới lập trình, sau đó gắn bó với câu trả lời của pad, điều này sẽ tốt hơn cho một lập trình viên mới.

Trong thế giới Object Oriented ai nghĩ rằng với các đối tượng và bằng các ngôn ngữ như vậy tôi sẽ bắt đầu với các đối tượng viết ra giấy và làm việc với nhiều sơ đồ như use-case, state transition, sequence diagram vv, cho đến khi tôi cảm thấy mình đã có đủ để bắt đầu tạo đối tượng trong các tệp C# cs, đưa ra các đối tượng bằng các phương thức, thuộc tính, sự kiện, v.v.

Trong thế giới chức năng, tôi thường bắt đầu với khái niệm trừu tượng và chuyển đổi thành discriminated unions (DU) trong tệp F # fs, bỏ qua sử dụng của một REPL, tức là F# Interactive, và sau đó bắt đầu thêm một vài chức năng. Sau khi tôi có một vài chức năng, tôi thiết lập dự án thử nghiệm bằng cách sử dụng NUnitFsUnit qua NuGet. Vì DU là trừu tượng, các trường hợp thử nghiệm thường khó viết hơn, vì vậy tôi tạo máy in cho DU và sau đó chèn chúng vào trường hợp kiểm tra nơi tôi thu được kết quả đầu ra từ máy in trong công cụ NUnit, để cắt và dán lại vào trường hợp kiểm tra thực hiện các thay đổi khi cần thiết. Xem these để biết các ví dụ về lý do tại sao tôi không viết chúng từ đầu bằng tay.

Khi tôi có DU trừu tượng được thực hiện, sau đó tôi có thể chuyển sang mã để chuyển đổi dạng con người/bê tông thành DU trừu tượng và chuyển DU trừu tượng thành dạng con người/bê tông. Trong một số trường hợp, chúng sẽ là parserspretty printers.

Điểm chính mà tôi đang cố gắng thực hiện là tôi không tập trung vào các công cụ tôi sử dụng mà dựa trên khái niệm trừu tượng của vấn đề và mang lại các công cụ khi cần.

Tôi sẽ lưu ý rằng tôi cũng có chương trình trong PROLOG và ở đó tôi bắt đầu với REPL và di chuyển mã đến cửa hàng khi logic hoạt động. Vì vậy, tôi không phản đối việc sử dụng REPL, nó chỉ là một cách khác để tiếp cận vấn đề.

EDIT

Theo yêu cầu của Ken để biết ví dụ.

Xem: Discriminated Unions (F#) và tìm kiếm phần
Using Discriminated Unions Instead of Object Hierarchies

Vì vậy, thay vì một kiểu cơ sở của hình dạng với các loại di truyền của Circle, EquilateralTriangle, Square và Rectangle người ta sẽ tạo ra một liên minh kỳ thị như đã nêu:

type Shape = 
| Circle of float 
| EquilateralTriangle of double 
| Square of double 
| Rectangle of double * double 

Khi câu hỏi của bạn sẽ làm cho một câu hỏi độc lập tốt hơn nhiều và nhận được câu trả lời với nhiều chi tiết tốt hơn tôi có thể đưa ra, tôi sẽ đề nghị bạn hỏi nó.

Ngoài ra nếu bạn tìm kiếm thông tin về vấn đề này cũng tìm kiếm với sự thay thế sau cho công đoàn bị phân biệt (DU):

+0

Thx vm. Có một chút để tiêu hóa ở đó - đặc biệt là các ví dụ! Tôi có nghĩ rằng bạn tạo DU ở gần cùng một điểm mà bạn bắt đầu tạo phân cấp đối tượng nếu làm việc trong C#, ví dụ, hoặc bạn đang nói một cái gì đó hơi khác nhau? Ngoài ra, có bạn một ví dụ về những gì bạn có nghĩa là khi bạn nói "tạo máy in cho DU" - StructuredFormatDisplayAttribute? –

+1

"Tôi có nghĩ rằng bạn tạo DU ở gần cùng một điểm mà bạn bắt đầu tạo phân cấp đối tượng nếu làm việc trong C#," Vâng, đó là cơ bản chính xác. Với OO bạn nghĩ các đối tượng đầu tiên, nhưng với chức năng bạn nghĩ trước, nhưng chức năng cần một số loại trước khi bạn có thể viết chúng và vì vậy cho bất cứ điều gì ngoài những điều cơ bản bạn có thể sẽ cần một DU. Lưu ý: Có thể thực hiện các dự án không cần DU vì nó là tất cả các chức năng của các kiểu cơ bản, vì vậy đừng nghĩ rằng DU luôn cần thiết, giống như bạn không cần một đối tượng trong ngôn ngữ OO để giải quyết vấn đề. –

+1

"Ngoài ra, bạn có một ví dụ về ý nghĩa của bạn khi bạn nói" tạo máy in cho DU ".Đó là một câu hỏi rất hay mà bạn nên hỏi ở đây trên SO. Tôi sẽ chỉ cho bạn một số ở đây, nhưng nghiêm túc hỏi người khác có thể cung cấp thêm thông tin về điều này. Xem: [fol.fs] (https://github.com/jack-pappas/fsharp-logic-examples/blob/master/FSharpx.Books.AutomatedReasoning/fol.fs) Bạn cũng cần để biết về AddPrinter Xem: [fol.fsx] (https://github.com/jack-pappas/fsharp-logic-examples/blob/master/Examples/fol.fsx) –

Các vấn đề liên quan