Thiết kế: Làm thế nào để tránh phá vỡ tính tương thích ngược vì thay đổi cơ sở dữ liệu


8

Đây là kịch bản của tôi, tôi có giao diện này:

public interface hitTheDataBase
{
    public void insertMe(String [] values);
    public void modifyMe(String [] values);
    public DataTable selectMe();
}

Và tôi có hai lớp này thực hiện giao diện:

public Class hitSqlServer implements hitTheDatabase
{
    public void insertMe(String [] values)
    {
         executes insert into table_in_sqlServerBD (col1, col2) values(values[0], values[1])
    }
    public void modifyMe(String [] values)
    {
         executes update table_in_sqlServerBD set col1 = values[0], col2 =  values[1] where rowid = values[3]
    }

    public DataTable selectMe()
    {
         executes select col1, col2 from table_in_sqlServerBD
    }
}

public Class hitSqLite implements hitTheDatabase
{
    public void insertMe(String [] values)
    {
         executes insert into table_in_sqLite (col1, col2) values(values[0], values[1])
    }
    public void modifyMe(String [] values)
    {
         executes update table_in_sqlLite set col1 = values[0], col2 =  values[1] where rowid = values[3]
    }

    public DataTable selectMe()
    {
         executes select col1, col2 from table_in_sqLite
    }
}

Đây là một phần của ứng dụng beta thực sự chạy trong môi trường thử nghiệm và trong sản xuất (!), Nhưng nó sẽ được cập nhật thường xuyên vì sửa lỗi không liên quan đến hoạt động của cơ sở dữ liệu. Các bản cập nhật được thực hiện đơn giản thông qua gỡ cài đặt và cài đặt lại.

Bây giờ, tôi có một yêu cầu mới cho một tình huống góc rất cụ thể sẽ cần thêm một cột "col3" mới vào bảng và tôi cũng sẽ phải chèn, chọn và cập nhật các giá trị trong cột đó. Vấn đề là tôi không muốn phá vỡ tính tương thích ngược với các cơ sở dữ liệu hiện có nơi phần mềm đang chạy.

Tôi đã suy nghĩ về việc mã hóa một lớp thứ ba thực hiện giao diện HitTheDataBase, một lớp trợ giúp để kiểm tra xem "col3" có tồn tại hay không và tạo ra một cái gì đó như:

hitTheDataBase hitMe = !helperclass.col3Exists() ? new hitSqlServer() : new hitSqlServerWithCol3();

Đây có phải là một cách tiếp cận tốt? Nó có vẻ tốt với tôi, ngoại trừ vì tôi sẽ cần sửa đổi mã trong các lớp sử dụng lớp "đánh vào cơ sở dữ liệu". Ngoài ra, tôi sẽ phải liên tục kiểm tra xem giá trị của col3 có tồn tại để hiển thị nó trong GUI hay không và cho phép người dùng sửa đổi nó.


2
Đây sẽ vẫn là một cách tiếp cận tốt nếu bạn cần làm điều này thêm 15 lần nữa?
Dan Pichelman

@DanPichelman không, Ben nói đúng: Mùi thiết kế :(
Broken_Window 10/03/2016

Mã ví dụ rất tệ đến nỗi tôi đã hít một hơi thật mạnh khi nhìn thấy nó.
Graham

@Graham, đó là một seudocode Java / C # khủng khiếp được thực hiện theo cách này vì không tiết lộ mã
propietary

Câu trả lời:


11

Khi các bản cập nhật phần mềm của bạn được triển khai, có lý do nào khiến bạn không thể nâng cấp lược đồ của mình không? Thay đổi phần mềm yêu cầu thay đổi lược đồ cơ sở dữ liệu ngụ ý rằng lược đồ sẽ thay đổi trên hệ thống đích.

Khả năng tương thích ngược với các phiên bản cũ hơn của lược đồ cơ sở dữ liệu thường là điều cần tránh và việc hack Lớp truy cập dữ liệu của bạn để hỗ trợ nhiều phiên bản lược đồ có cảm giác như mùi thiết kế.

Một giải pháp sạch hơn là đảm bảo rằng mã của bạn luôn chạy theo phiên bản của lược đồ mà mã đó đã được viết. Điều này không chỉ giúp mã dễ viết hơn và giữ mã sạch hơn mà còn giúp mã dễ kiểm tra hơn. Bạn có thể bao gồm các tập lệnh di chuyển như là một phần của quá trình cài đặt / gỡ cài đặt để nâng cấp cũng như khôi phục.

Lược đồ của bạn có bao gồm bất kỳ loại bảng phiên bản nào không? Nếu không, bạn cần thêm một bảng phiên bản lược đồ càng sớm càng tốt. Phiên bản Schema là rất quan trọng để nâng cấp và rollback.

Trong một khoảng thời gian dài hơn, bạn có thể sẽ kết thúc với rất nhiều tập lệnh nâng cấp lược đồ sẽ cần được thực hiện theo một thứ tự cụ thể trong quá trình cài đặt / gỡ cài đặt. Một cơ chế phiên bản lược đồ là chìa khóa để đảm bảo rằng các nâng cấp và rollback lược đồ chạy trơn tru.

Mặt khác, nếu bạn không có cơ chế giữ sơ đồ của mình cùng với phiên bản phần mềm, thì Lớp truy cập dữ liệu của bạn cuối cùng có thể phát nổ phức tạp khi bạn phải đối mặt với số lượng "hack" ngày càng tăng để bảo vệ lạc hậu khả năng tương thích; và bạn sẽ phải chịu gánh nặng với việc kiểm tra hồi quy ngày càng tăng mỗi khi bạn thay đổi bất cứ điều gì trong lược đồ của mình.


1

Đây là những gì xảy ra nếu lược đồ cơ sở dữ liệu của bạn không khớp với phiên bản ứng dụng. Bất kỳ ứng dụng nào nhận được mã col3 mới, nên có cơ sở dữ liệu được cập nhật cùng với nó.

Nếu bạn gặp khó khăn trong việc kiểm tra xem một cột có tồn tại trong bảng hay không, chỉ cần tạo nó trong khi cập nhật lên phiên bản mới hơn.


Bạn nói đúng, lược đồ ứng dụng và bd phải khớp. Tôi đã thực hiện "tạo các cột bị thiếu" trong quá khứ. Nó chỉ hoạt động nếu người dùng tôi đang sử dụng cho kết nối cơ sở dữ liệu có đủ đặc quyền và điều này không phải lúc nào cũng đúng.
Broken_Window 10/03/2016

Sau đó, quản trị viên hệ thống của họ cần chạy tập lệnh cập nhật mà bạn đang cung cấp cho họ.
RubberDuck

@RubberDuck đó là giải pháp tôi đã sử dụng. Tôi đã bao gồm các tập lệnh cập nhật với các tệp cài đặt và cách cập nhật cơ sở dữ liệu trong Hướng dẫn sử dụng.
Broken_Window 10/03/2016

1

Tôi sẽ nói không.

Loại [vô tận] "nếu, nhưng, có lẽ, trừ khi, ngoại trừ" logic sẽ chỉ khiến bạn phát điên và quan trọng hơn là làm chậm ứng dụng của bạn, bởi vì tất cả các "kiểm tra" này đang được thực hiện trong thời gian chạy.

Tôi muốn đề nghị versioning thay đổi sơ đồ của bạn và lưu trữ rằng phiên bản [số] nơi nào đó trong cơ sở dữ liệu (như một phần của tiến trình nâng cấp của bạn).

Tạo một phiên bản của lớp truy cập dữ liệu của bạn cho mỗi phiên bản cơ sở dữ liệu.

Trong thời gian chạy, thẩm vấn cơ sở dữ liệu cho phiên bản lược đồ và khởi tạo lớp "đúng" dựa trên đó.


2
Bạn có thể muốn đề cập rằng câu cuối cùng của bạn là một tham chiếu đến mẫu Chiến lược .
TMN
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.