Chiến lược truyền đối số - biến môi trường so với dòng lệnh


76

Hầu hết các ứng dụng mà nhà phát triển chúng tôi viết cần phải được tham số hóa bên ngoài khi khởi động. Chúng tôi chuyển các đường dẫn tệp, tên đường ống, địa chỉ TCP / IP, v.v. Cho đến nay, tôi đã sử dụng dòng lệnh để chuyển các đường dẫn này tới ứng dụng đang được khởi chạy. Tôi đã phải phân tích cú pháp dòng lệnh mainvà hướng các đối số đến nơi chúng cần, tất nhiên đây là một thiết kế tốt , nhưng khó duy trì đối với một số lượng lớn các đối số. Gần đây tôi đã quyết định sử dụng cơ chế biến môi trường . Chúng có tính toàn cầu và có thể truy cập từ mọi nơi, điều này kém thanh lịch hơn theo quan điểm kiến ​​trúc, nhưng giới hạn số lượng mã .

Đây là những ấn tượng đầu tiên (và có thể khá nông cạn) của tôi về cả hai chiến lược nhưng tôi muốn nghe ý kiến ​​của các nhà phát triển có kinh nghiệm hơn - Những thăng trầm của việc sử dụng các biến môi trường và đối số dòng lệnh để chuyển đối số cho một quy trình là gì? Tôi muốn tính đến những vấn đề sau:

  1. chất lượng thiết kế (tính linh hoạt / khả năng bảo trì),
  2. hạn chế về bộ nhớ,
  3. tính di động của giải pháp.

Nhận xét:

Quảng cáo. 1. Đây là khía cạnh chính mà tôi quan tâm.

Quảng cáo. 2. Điều này hơi thực dụng. Tôi biết một số hạn chế trên Windows hiện đang rất lớn (hơn 32kB cho cả dòng lệnh và khối môi trường). Mặc dù vậy, tôi đoán đây không phải là vấn đề vì bạn chỉ nên sử dụng một tệp để chuyển hàng tấn đối số nếu cần.

Quảng cáo. 3. Tôi hầu như không biết gì về Unix vì vậy tôi không chắc liệu cả hai chiến lược có khả dụng tương tự như trên Windows hay không. Xây dựng về điều này nếu bạn vui lòng.


Bạn có cung cấp chi tiết cụ thể hơn, như trong số lượng thông số thực tế không? và nếu có các nhóm cho chúng hoặc tất cả chúng là ngẫu nhiên? và ngôn ngữ này dùng để làm gì? java, c ++, v.v. Lý do tôi yêu cầu mức độ chi tiết đó là mặc dù có thể là một vấn đề cần giải quyết bằng bất kỳ ngôn ngữ nào, nhưng có thể có một giải pháp triển khai ngôn ngữ cụ thể mà bạn không biết.
James Drinkard

Chỉ cần đề cập đến hệ điều hành * nix, chúng không có gì giống như "biến môi trường toàn cầu" và mỗi env var được kế thừa từ quy trình mẹ sang quy trình con vào thời gian fork. Vì vậy, "toàn cầu" không phải là một phần mềm chuyên nghiệp cho env var qua dòng lệnh, ít nhất là cho các hệ điều hành đó.
shr

Xin chào, @jamesDrinkard. Tôi quan tâm đến cách tiếp cận chung. Nếu bạn muốn chuyển 20 đối số chuỗi / tích phân / số thực có nhãn khác nhau từ tập lệnh Python chạy bởi trình thông dịch 32 bit sang ứng dụng 64 bit được viết bằng C ++, bạn sẽ sử dụng phương pháp nào?
Janusz Lenar

Xin chào, @shr. Cảm ơn bạn đã ghi chú * nix. Như Raymond đã chỉ ra bên dưới, đối với nhiệm vụ này, tính toàn cầu như vậy không phải là chuyên nghiệp chút nào.
Janusz Lenar

1
Điều này có thể có liên quan và ủng hộ các biến môi trường: devcenter.heroku.com/articles/config-vars
eyeApps LLC

Câu trả lời:


77

1) Tôi khuyên bạn nên tránh các biến số môi trường càng nhiều càng tốt.

Ưu điểm của các biến môi trường

  • dễ sử dụng vì chúng có thể nhìn thấy từ mọi nơi. Nếu nhiều chương trình độc lập cần một thông tin, thì cách tiếp cận này thuận tiện hơn rất nhiều.

Nhược điểm của các biến môi trường

  • khó sử dụng chính xác vì chúng có thể nhìn thấy (có thể xóa, có thể thiết lập) từ mọi nơi. Nếu tôi cài đặt một chương trình mới dựa trên các biến môi trường, liệu chúng có sử dụng các biến hiện có của tôi không? Có phải tôi đã vô tình làm hỏng các biến số môi trường của mình khi tôi đang hoành tráng ngày hôm qua không?

Ý kiến ​​cá nhân của tôi

  • sử dụng các đối số dòng lệnh cho những đối số có nhiều khả năng khác nhau đối với từng lệnh gọi riêng lẻ của chương trình (tức là n cho một chương trình tính toán n!)
  • sử dụng tệp cấu hình cho các đối số mà người dùng có thể muốn thay đổi một cách hợp lý, nhưng không thường xuyên (tức là kích thước hiển thị khi cửa sổ bật lên)
  • sử dụng các biến môi trường một cách tiết kiệm - chỉ ưu tiên cho các đối số được cho là không thay đổi (tức là vị trí của trình thông dịch Python)
  • quan điểm của bạn They are global and accessible from anywhere, which is less elegant from architectural point of view, but limits the amount of codenhắc tôi về những biện minh cho việc sử dụng các biến toàn cục;)

Những vết sẹo của tôi do tận mắt trải qua sự khủng khiếp của việc lạm dụng quá mức các biến đổi môi trường

  • hai chương trình chúng ta cần tại nơi làm việc không thể chạy cùng lúc trên cùng một máy tính do xung đột môi trường
  • nhiều phiên bản của các chương trình có cùng tên nhưng lỗi khác nhau - đã khiến cả một hội thảo phải điêu đứng trong nhiều giờ vì vị trí của chương trình bị lấy ra khỏi môi trường và (một cách âm thầm, tinh vi) đã sai.

2) Giới hạn

Nếu tôi đang đẩy giới hạn của những gì dòng lệnh có thể giữ hoặc những gì môi trường có thể xử lý, tôi sẽ cấu trúc lại ngay lập tức.

Trước đây tôi đã sử dụng JSON cho một ứng dụng dòng lệnh cần rất nhiều tham số. Rất tiện lợi khi có thể sử dụng từ điển và danh sách, cùng với chuỗi và số. Ứng dụng chỉ lấy một vài args dòng lệnh, một trong số đó là vị trí của tệp JSON.

Ưu điểm của phương pháp này

  • không cần phải viết nhiều mã (khó khăn) để tương tác với thư viện CLI - có thể là một điều khó khăn khi khiến nhiều thư viện phổ biến thực thi các ràng buộc phức tạp (bởi 'phức tạp', ý tôi là phức tạp hơn việc kiểm tra một khóa cụ thể hoặc sự thay thế giữa một bộ khóa)
  • không phải lo lắng về các yêu cầu của thư viện CLI đối với thứ tự của các đối số - chỉ cần sử dụng một đối tượng JSON!
  • dễ biểu diễn dữ liệu phức tạp (trả lời What won't fit into command line parameters?) như danh sách
  • dễ dàng sử dụng dữ liệu từ các ứng dụng khác - cả để tạo và phân tích cú pháp theo chương trình
  • dễ dàng điều chỉnh các tiện ích mở rộng trong tương lai

Lưu ý : Tôi muốn phân biệt điều này với phương pháp .config-file - phương pháp này không phải để lưu trữ cấu hình người dùng. Có lẽ tôi nên gọi đây là cách tiếp cận 'tệp tham số dòng lệnh', vì tôi sử dụng nó cho một chương trình cần nhiều giá trị không phù hợp với dòng lệnh.


3) Tính di động của giải pháp: Tôi không biết nhiều về sự khác biệt giữa Mac, PC và Linux liên quan đến các biến môi trường và đối số dòng lệnh, nhưng tôi có thể cho bạn biết:

  • cả ba đều hỗ trợ cho các biến môi trường
  • tất cả chúng đều hỗ trợ các đối số dòng lệnh

Vâng, tôi biết - nó không hữu ích lắm. Tôi xin lỗi. Nhưng điểm mấu chốt là bạn có thể mong đợi một giải pháp hợp lý có tính di động, mặc dù bạn chắc chắn muốn xác minh điều này cho các chương trình của mình (ví dụ: args dòng lệnh có phân biệt chữ hoa chữ thường trên bất kỳ nền tảng nào trên tất cả các nền tảng không? Tôi không biết ).


Một điểm cuối cùng:

Như Tomasz đã đề cập, nó không quan trọng đối với hầu hết các ứng dụng mà các tham số đến từ đâu.


Cảm ơn, Matt. Đây là một loại ý kiến ​​mà tôi đang tìm kiếm. Lời khuyên quan trọng nhất của bạn là sử dụng các biến môi trường cho mô tả môi trường thực thi, điều này hầu như không thay đổi và tệp cmd để thực thi thực tế các đối số đơn giản / phức tạp. Rất hợp lý, cảm ơn. Lưu ý rằng bạn có thể sử dụng các biến môi trường 'cục bộ' chỉ có thể làm rối các quy trình con. Nó rất giống với các đối số dòng lệnh truyền, ngoại trừ những gì Raymond đã chỉ ra dưới câu trả lời của Tomasz.
Janusz Lenar

1
Câu trả lời rất hay! Liên quan đến nhược điểm là các biến môi trường có thể được thay đổi từ bất kỳ đâu: Cũng có khả năng đặt các biến môi trường cục bộ từ một tập lệnh bắt đầu (ví dụ: tập lệnh Bash hoặc Batch) cho ứng dụng. Trong trường hợp đó, có thể có giá trị mặc định trên toàn hệ thống, nhưng nếu cần ứng dụng có thể thay đổi giá trị mặc định thành giá trị tùy chỉnh. suy nghĩ của bạn về điều đó là gì?
Lii

Có bất kỳ ưu và nhược điểm nào khi xem xét cách chuyển các bí mật / thông tin đăng nhập?
iamyojimbo

Tôi đồng ý cho các ứng dụng máy tính để bàn và CLI. Đối với hệ thống điện toán đám mây có nhiều triển khai, biến env là một lựa chọn tốt và ví dụ khuyến cáo trong hướng dẫn sử 12factor: 12factor.net/config
Lars Grammel

7

Bạn nên đọc tóm tắt các tham số bằng cách sử dụng mẫu Chiến lược . Tạo một sự trừu tượng tên là ConfigurationSourcereadConfig(key) -> valuephương pháp (hoặc trả lại một số Configurationđối tượng / cấu trúc) với hiện thực sau đây:

  • CommandLineConfigurationSource
  • EnvironmentVariableConfigurationSource
  • WindowsFileConfigurationSource - tải từ tệp cấu hình từ C:/Document and settings...
  • WindowsRegistryConfigurationSource
  • NetworkConfigrationSource
  • UnixFileConfigurationSource - - tải từ tệp cấu hình từ /home/user/...
  • DefaultConfigurationSource - mặc định
  • ...

Bạn cũng có thể sử dụng mẫu Chuỗi trách nhiệm cho chuỗi nguồn trong các cấu hình khác nhau như: nếu đối số dòng lệnh không được cung cấp, hãy thử biến môi trường và nếu mọi thứ khác không thành công, hãy trả về mặc định.

Quảng cáo 1. Cách tiếp cận này không chỉ cho phép bạn đọc tóm tắt cấu hình mà bạn có thể dễ dàng thay đổi cơ chế bên dưới mà không ảnh hưởng đến mã máy khách. Ngoài ra, bạn có thể sử dụng nhiều nguồn cùng một lúc, dự phòng hoặc thu thập cấu hình từ các nguồn khác nhau.

Quảng cáo 2. Chỉ cần chọn bất kỳ cách triển khai nào phù hợp. Tất nhiên, một số mục cấu hình sẽ không phù hợp với các đối số dòng lệnh.

Quảng cáo 3. Nếu một số triển khai không có tính di động, hãy có hai, một triển khai âm thầm bị bỏ qua / bỏ qua khi không phù hợp với một hệ thống nhất định.


Cảm ơn bạn, đây thường là một ý kiến ​​hay. Nhưng nó không giúp ích gì với quyết định sử dụng môi trường hay dòng lệnh. Việc xây dựng trên Ad.2. 'một số mục cấu hình chẳng hạn sẽ không phù hợp với các đối số dòng lệnh' sẽ hữu ích. Những gì sẽ không phù hợp với một chuỗi? Nếu nó không phù hợp, nó có lẽ nên được chuyển gián tiếp trong một loại tệp, phải không?
Janusz Lenar

Quan điểm của tôi là: không buộc người dùng sử dụng tham số dòng lệnh hoặc biến môi trường. Hãy linh hoạt (nhưng vẫn duy trì mã có thể bảo trì). Tôi tin rằng tệp cấu hình là nơi tốt nhất để lưu trữ cấu hình (nó có thể dài tùy ý, chứa các nhận xét, v.v.), tuy nhiên, đôi khi việc ghi đè cấu hình tệp bằng các tham số dòng lệnh sẽ rất hữu ích. Điều gì sẽ không phù hợp với các tham số dòng lệnh? Nếu bạn cần chuyển một số đường dẫn tệp, nó có thể sẽ hoạt động, nhưng không ai thích các dòng lệnh quá dài.
Tomasz Nurkiewicz,

Tệp cấu hình là tốt nhất cho các đối số - đây là ý kiến ​​có giá trị và hỗ trợ cho các nhận xét là lý do chính đáng để sử dụng nó, cảm ơn bạn. Nếu bạn sử dụng các biến môi trường khi khởi chạy ứng dụng từ tập lệnh lô, bạn có thể có một biểu mẫu rất dễ đọc bằng cách sử dụng remset. Nếu bạn đang tạo ra một quá trình, bạn chỉ cần setenvnhững gì bạn muốn trước khi spawnl-ing. Nó thuận tiện, dễ đọc và linh hoạt. Tại sao bạn lại sử dụng .config thay vì môi trường? Đó là câu hỏi.
Janusz Lenar

3
Lưu ý rằng các biến môi trường được kế thừa. Giả sử chương trình của bạn có hai tham số ACTIONvà một tùy chọn NOTIFY. Chương trình A thiết lập ACTION=if owner=nobody set owner=bobNOTIFY=sendsau đó chạy chương trình của bạn. Chương trình của bạn cập nhật một mục, sau đó thấy mục đó đã NOTIFYđược thiết lập và chạy send. Các sendchương trình sẽ gửi email cho Bob và sau đó chạy chương trình của bạn một lần nữa, thiết lập ACTION=set last_send = today. Nó không muốn bất kỳ thông báo nào, vì vậy nó không đặt NOTIFY. Nhưng nó kế thừa NOTIFY từ chương trình A, vì vậy chương trình của bạn cập nhật lần chạy cuối cùng cho đến ngày hôm nay và sau đó chạy send. Vòng lặp vô hạn.
Raymond Chen

1
Cảm ơn bạn, @Raymond. Phạm vi của các biến môi trường rất rộng. Điểm tốt.
Janusz Lenar

4

Tôi nghĩ câu hỏi này đã được trả lời khá tốt, nhưng tôi cảm thấy nó xứng đáng được cập nhật vào năm 2018. Tôi cảm thấy như một lợi ích chưa được đề cập của các biến môi trường là chúng thường yêu cầu ít mã tấm lò hơi hơn để làm việc. Điều này làm cho mã dễ đọc hơn. Tuy nhiên, một nhược điểm lớn là chúng loại bỏ một lớp cách ly với các ứng dụng khác nhau chạy trên cùng một máy. Tôi nghĩ đây là nơi Docker thực sự tỏa sáng. Mẫu thiết kế yêu thích của tôi là sử dụng độc quyền các biến môi trường và chạy ứng dụng bên trong vùng chứa Docker. Điều này loại bỏ vấn đề cô lập.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.