2013-05-28 21 views
16

Something Tôi luôn tò mò củaThử/Bắt trong Constructor - Khuyến cáo thực hành?

public class FileDataValidator { 

private String[] lineData; 

public FileDataValidator(String[] lineData){ 

    this.lineData = lineData; 
    removeLeadingAndTrailingQuotes(); 

    try 
    { 
     validateName(); 
     validateAge(); 
     validateTown(); 
    } 
    catch(InvalidFormatException e) 
    { 
     e.printStackTrace(); 
    } 

} 

//validation methods below all throwing InvalidFormatException 

là không nên bao gồm các khối try/catch trong Constructor của tôi? Tôi biết tôi có thể có Constructor ném ngoại lệ trở lại cho người gọi. Những gì bạn thích trong các phương pháp gọi như tôi đã làm trong Constructor? Trong lớp gọi điện thoại, bạn muốn tạo một thể hiện của FileDataValidator và gọi các phương thức đó trên cá thể đó? Chỉ cần quan tâm để nghe một số thông tin phản hồi!

+3

Điều quan trọng hơn là bạn sẽ làm gì với 'e' trong trường hợp API,' printStackTrace' có mùi buồn cười. Chắc chắn bạn nên cho phép người dùng mã gặp phải ngoại lệ để họ có thể làm điều gì đó về nó? Đó là những ngoại lệ. –

+0

Tại sao không thay đổi các hoạt động 'validateXXX' để trả về các boolean và sau đó thiết lập một biến gọi là' valid' là nếu cả ba lệnh 'validateXXX' đều hợp lệ. Sau đó, lộ ra rằng var ra với một phương pháp 'isValid' – cmbaxter

+0

Làm một cái gì đó với [Command Pattern] (http://en.wikipedia.org/wiki/Command_pattern) có thể giúp đỡ ở đây; tức là, khởi tạo một phương thức bạn sẽ gọi nhiều lần, truyền dữ liệu để xác nhận hợp lệ và để phương thức đó thực hiện thao tác ném ngoại lệ. –

Trả lời

15

Trong mã bạn hiển thị, các vấn đề xác thực không giao tiếp ngược lại mã đang tạo đối tượng đối tượng này. Đó có lẽ không phải là một điều TỐT.

Biến thể 1:

Nếu bạn nắm bắt được ngoại lệ bên trong phương pháp/constructor, hãy chắc chắn để vượt qua một cái gì đó lại cho người gọi. Bạn có thể đặt một trường isValid được đặt thành true nếu tất cả hoạt động. Điều đó sẽ trông như thế này:

private boolean isValid = false; 

public FileDataValidator(String[] lineData){ 

    this.lineData = lineData; 
    removeLeadingAndTrailingQuotes(); 

    try 
    { 
     validateName(); 
     validateAge(); 
     validateTown(); 
     isValid = true; 
    } 
    catch(InvalidFormatException e) 
    { 
     isValid = false; 
    } 
} 

public boolean isValid() { 
    return isValid; 
} 

Biến thể 2:

Hoặc bạn có thể cho phép các ngoại lệ hay một số ngoại lệ khác tuyên truyền để người gọi. Tôi đã cho thấy nó như là một ngoại lệ không được kiểm tra nhưng làm bất cứ điều gì làm việc theo xử lý tôn giáo ngoại trừ của bạn:

public FileDataValidator(String[] lineData){ 

    this.lineData = lineData; 
    removeLeadingAndTrailingQuotes(); 

    try 
    { 
     validateName(); 
     validateAge(); 
     validateTown(); 
    } 
    catch(InvalidFormatException e) 
    { 
     throw new com.myco.myapp.errors.InvalidDataException(e.getMessage()); 
    } 

} 

Biến thể 3:

Phương pháp thứ ba tôi muốn đề cập đến có mã như thế này. Trong mã gọi, bạn phải gọi hàm khởi tạo và sau đó gọi hàm build() sẽ hoạt động hay không.

String[] lineData = readLineData(); 
FileDataValidator onePerson = new FileDataValidator(); 
try { 
    onePerson.build(lineData); 
} catch (InvalidDataException e) { 
    // What to do it its bad? 
} 

Đây là mã lớp:

public FileDataValidator() { 
    // maybe you need some code in here, maybe not 
} 

public void build(String[] lineData){ 

    this.lineData = lineData; 
    removeLeadingAndTrailingQuotes(); 

    try 
    { 
     validateName(); 
     validateAge(); 
     validateTown(); 
    } 
    catch(InvalidFormatException e) 
    { 
     throw new com.myco.myapp.errors.InvalidDataException(e.getMessage()); 
    } 

} 

Tất nhiên, build() chức năng có thể sử dụng một phương pháp isValid() mà bạn gọi điện để xem có phù hợp của nó nhưng một ngoại lệ dường như đúng cách để tôi cho chức năng xây dựng.

Biến thể 4:

Phương pháp thứ tư tôi muốn đề cập đến là những gì tôi thích nhất. Nó có mã như thế này. Trong mã gọi, bạn phải gọi hàm khởi tạo và sau đó gọi hàm build() sẽ hoạt động hay không.

Loại này theo cách hoạt động của JaxB và JaxRS, đây là tình huống tương tự với những gì bạn có.

  1. Nguồn dữ liệu bên ngoài - bạn có tệp, họ có thư đến ở định dạng XML hoặc JSON.
  2. Mã để tạo các đối tượng - bạn có mã của mình, chúng có thư viện mã hoạt động theo các đặc điểm kỹ thuật trong các JSR khác nhau.
  3. Xác thực không được gắn với việc xây dựng các đối tượng.

Mã gọi:

String[] lineData = readLineData(); 
Person onePerson = new Person(); 
FileDataUtilities util = new FileDataUtilities(); 
try { 
    util.build(onePerson, lineData); 
    util.validate(onePerson); 
} catch (InvalidDataException e) { 
    // What to do it its bad? 
} 

Đây là mã lớp học, nơi các dữ liệu sống:

public class Person { 
    private Name name; 
    private Age age; 
    private Town town; 
... lots more stuff here ... 
} 

Và mã tiện ích để xây dựng và xác nhận:

public FileDataValidator() { 
    // maybe you need some code in here, maybe not 
} 

public void build(Person person, String[] lineData){ 

    this.lineData = lineData; 
    removeLeadingAndTrailingQuotes(); 
    setNameFromData(person); 
    setAgeFromData(person); 
    setTownFromData(person); 
} 

public boolean validate(Person person) { 

    try 
    { 
     validateName(person); 
     validateAge(person); 
     validateTown(person); 
     return true; 
    } 
    catch(InvalidFormatException e) 
    { 
     throw new com.myco.myapp.errors.InvalidDataException(e.getMessage()); 
    } 

} 
+0

Loại đầu tiên của bạn bị hỏng (phương thức _within_ constructor?) Và thứ hai chỉ là một bài tập trong dự phòng. –

+0

@GrantThomas Tôi rất thích nghe nhiều hơn. Tôi thấy không có vấn đề gọi phương pháp trong constructor, nếu họ phục vụ một mục đích hữu ích. Có lẽ bạn có thể giải thích. OP sẽ phải quyết định những gì hữu ích. Thứ hai, bạn đang nói 'catch-rethrow' là dư thừa? –

+1

@LeeMeador Cảm ơn bạn đã dành rất nhiều thời gian viết ra một số ý tưởng! Họ cung cấp rất nhiều thức ăn cho tư tưởng. Tôi nghĩ rằng tôi sẽ đi với biến thể 3. Di chuyển các cuộc gọi xác nhận từ constructor và propogating ngoại lệ cho người gọi là thân thiện hơn nhiều về việc có thể tái sử dụng một đối tượng duy nhất, và lớp gọi là phù hợp hơn để biết những gì sẽ xảy ra nếu dữ liệu không hợp lệ đã được thông qua. – deanmau5

2

Sở thích của tôi là dành cho các trường hợp ngoại lệ được xử lý bởi bit code biết làm thế nào để đối phó với họ. Trong trường hợp này, tôi sẽ giả định rằng bit của mã tạo ra một FileDataValidator biết những gì sẽ xảy ra nếu dữ liệu tập tin không hợp lệ, và các trường hợp ngoại lệ cần được xử lý ở đó (tôi đang ủng hộ tuyên truyền cho người gọi).

Trong khi thảo luận về thực tiễn tốt nhất - tên lớp FileDataValidator có mùi đối với tôi. Nếu đối tượng bạn đang tạo lưu trữ dữ liệu tệp thì tôi sẽ gọi nó là FileData - có lẽ với phương thức xác thực? Nếu bạn chỉ muốn xác thực dữ liệu tệp của mình thì phương thức tĩnh sẽ đủ.

+0

+1 để nhận thấy tên lớp cần được cải thiện. –

2

Bạn nên xem xét mẫu nhà máy tĩnh. Đặt hàm tạo của tất cả đối số của bạn ở chế độ riêng tư. Cung cấp phương thức FileDataValidator (args ...) tĩnh. Điều này chấp nhận và xác nhận tất cả các đối số. Nếu mọi thứ đều ổn, nó có thể gọi hàm tạo riêng và trả về đối tượng mới được tạo ra. Nếu bất cứ điều gì không thành công, hãy ném một ngoại lệ để thông báo cho người gọi rằng nó cung cấp các giá trị xấu.

Tôi cũng phải đề cập đến điều này: bắt (Ngoại lệ e) { printSomeThing (e); }

Mẫu antipattern nguy hiểm nhất mà bạn có thể thực hiện với Ngoại lệ. Có, bạn có thể đọc một số giá trị lỗi trên dòng lệnh và sau đó? Người gọi (người cung cấp các giá trị xấu) không được thông báo về các giá trị xấu, việc thực thi chương trình sẽ tiếp tục.

+0

Xin cảm ơn vì đã gợi ý điều này. Im rất nhiều cho việc thực hiện các mẫu mã của tôi và đây là một cái gì đó tôi chắc chắn sẽ chơi xung quanh với. Cảm ơn lời khuyên chống mẫu cũng! Thành thật mà nói tôi chỉ có nó cho mục đích dev cho đến khi tôi làm việc ra một giải pháp cho câu hỏi ban đầu! – deanmau5

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