2010-03-22 25 views
79

Có bất kỳ nguyên tắc thiết kế, thực hành tốt nhất và các mẫu thiết kế nào đã biết mà người ta có thể làm theo trong khi thiết kế một dự án C không? Hoặc các nguyên tắc thiết kế hữu ích cho lập trình thủ tục (bắt buộc) nói chung?Nguyên tắc thiết kế, thực tiễn tốt nhất và mẫu thiết kế cho C (hoặc lập trình thủ tục nói chung)?

(tôi con của 'thế hệ hướng đối tượng' và phải thiết kế một dự án C lớn lần đầu tiên)

+1

Bạn có thể quan tâm đến anwsers cho câu hỏi này: http://stackoverflow.com/questions/661307/recommendations-for-structuring-complex-applications-in-c – mouviciel

+0

Thật vậy, cảm ơn bạn rất nhiều, mouviciel. – Dimi

+7

Tôi đã thực hiện một số nghiên cứu về thư viện đại học và internet, trước khi đăng câu hỏi, và chắc chắn không bị choáng ngợp với sách về thiết kế phần mềm cho C. Tôi yêu cầu bạn yêu thích (không nói về sách C nói chung, không nói về các quy ước mã hóa như ý nghĩa tên biến, nhưng về mức trừu tượng cao hơn, mức kiến ​​trúc phần mềm). Hơn nữa, tôi không đồng ý với sự sỉ nhục của bạn. Bạn có nghĩa là mỗi lập trình viên nên tự tìm hiểu về các phương pháp hay nhất và các mẫu thiết kế tốt? Đây là câu hỏi chắc chắn về trải nghiệm của người khác phải được sử dụng. – Dimi

Trả lời

56

Thông tin ẩn - như tán thành bởi Parnas (Software Fundamentals).

quản lý cẩn thận các tiêu đề và visibility:

  • Tất cả mọi thứ trong một tập tin nguồn có thể được ẩn từ thế giới bên ngoài nên được; chỉ cần hiển thị giao diện bên ngoài được ghi lại.
  • Mọi thứ được hiển thị được khai báo trong tiêu đề.
  • Tiêu đề đó được sử dụng khi cần chức năng (và nơi chức năng được xác định).
  • Tiêu đề là độc lập - khi bạn cần, bạn sử dụng nó và bạn không phải băn khoăn về 'các tiêu đề khác mà tôi cũng phải đưa vào' vì tiêu đề đảm bảo nó hoạt động bằng cách bao gồm mọi thứ cần thiết Để làm cho nó hoạt động.
  • Tiêu đề được tự bảo vệ - vì vậy không quan trọng nếu nó được bao gồm nhiều lần.

    #ifndef HEADER_H_INCLUDED 
    #define HEADER_H_INCLUDED 
    ...rest of header contents, including other #include lines if necessary 
    #endif /* HEADER_H_INCLUDED */ 
    
  • bộ thiết kế các chức năng để làm việc trên 'đối tượng' (thường cấu trúc) - và sử dụng những chức năng chứ không phải là chọc xung quanh nội tạng của cấu trúc trong các mã được sử dụng nó. Hãy suy nghĩ về nó như là đóng gói tự áp đặt.

+0

Điểm tốt, cảm ơn bạn, Jonathan. Các kiểu dữ liệu trừu tượng là một ví dụ khác về ẩn thông tin với việc tách biệt việc sử dụng và triển khai thực hiện (giao diện bên ngoài đã biết và triển khai nội bộ không xác định). – Dimi

20

Có một tốt, miễn phí, sách trực tuyến, với tựa đề Object-Oriented Programming With ANSI-C, trong đó bao gồm các chủ đề về viết code hướng đối tượng trong C. Một google search cho "hướng đối tượng C" cũng mang lại một số ví dụ điển hình khác và tài nguyên.

Nếu dự án của bạn là an toàn quan trọng, MISRA-C là một bộ quy tắc tốt. Nó được thiết kế chủ yếu cho nhúng c, nhưng nó có thể hữu ích trong các lĩnh vực khác.

Tôi tự coi mình là trình mã hóa OO và tôi làm rất nhiều việc với nhúng-C. Lời khuyên tốt nhất tôi có thể đưa ra, đặc biệt là cho các dự án lớn, không phải là để lạm dụng nó. Việc tạo một khuôn khổ OO hoàn chỉnh trên đầu ANSI C có thể rất hấp dẫn, nhưng phải mất rất nhiều thời gian và công sức để làm cho nó đúng. Bạn càng có nhiều fancier, bạn càng mất nhiều thời gian để gỡ lỗi khung công tác thay vì làm việc trên dự án thực sự. Tiếp cận nhiệm vụ với một cái đầu rõ ràng, và nắm bắt tốt, vững chắc của YAGNI. May mắn nhất!

+0

Cảm ơn bạn, e.James. Tôi không muốn tạo một khung hướng đối tượng trên đầu trang của ANSI C, nhưng hãy tìm các nguyên tắc thiết kế lập trình thủ tục đặc biệt và thích hợp. MISRA-C gợi ý rất hữu ích, đặc biệt là vì nó thực sự là một dự án nhúng. Tôi sẽ xem xét kỹ hơn. – Dimi

+0

Ah, niềm vui của nhúng C. Đừng quên rằng bạn phải khai báo các biến của bạn ở phía trên cùng của hàm của bạn (hoặc ở đầu bất kỳ khối '{}' nào). Điều đó luôn luôn cắn tôi một lần hoặc hai lần ':)' –

6

OOP là phương pháp không phải là công nghệ. Vì vậy, lời khuyên đầu tiên của tôi là ngừng suy nghĩ về nó như là lập trình thủ tục.

Đến điểm của e.James, bạn không muốn thử và tạo lại ngôn ngữ hướng đối tượng hoặc giả vờ rằng bạn có khả năng của ngôn ngữ đó. Bạn vẫn có thể làm tất cả những điều đúng bằng cách bám vào một vài nguyên tắc đơn giản:

  1. Kiểm tra mọi thứ.
  2. Tìm những gì khác nhau và đóng gói nó.
  3. Thiết kế giao diện.
19

My ba lời khuyên:

  • kiểm tra Viết đơn vị. Họ sẽ giúp bạn không ở trên một thiết kế mà bộ vấn đề của bạn khi bạn đi cùng. Tốt hơn nhiều so với việc chỉ dựa vào suy nghĩ trước khi thiền định.
  • Có bộ dò tìm rò rỉ bộ nhớ (có tất cả các loại thư viện ngoài đó) được cài đặt và chạy từ ngày đầu tiên. Có thư viện này in ra tất cả các rò rỉ ngay sau khi thoát khỏi chương trình/kiểm tra. Điều này sẽ cho phép bạn để bắt một rò rỉ ngay sau khi bạn giới thiệu nó, do đó làm cho nó sửa chữa ít đau đớn hơn nhiều.
  • Viết mã OOP vào C. Không khó. Mặc dù có thể mô phỏng được trọng số của phương pháp, tôi khuyên bạn nên bắt đầu với mô phỏng các đối tượng đơn giản. Ngay cả cơ chế đơn giản này cũng có thể mang lại cho bạn số dặm lớn.

Dưới đây là một ví dụ:

struct Vector { 
    int size; 
    int limit; 
    int* ints; 
} 

Vector* Vector_new() { 
    Vector* res = (Vector*) malloc(sizeof(Vector)); 
    res->limit = 10; 
    res->size = 0; 
    res->ints = (int*) malloc(sizeof(int) * res.limit); 

    return res; 
} 


void Vector_destroy(Vector* v) { 
    free(v->ints); 
    free(v); 
} 

void Vector_add(Vector* v, int n) { 
    if(v->size == v->limit) { 
    v->limit = v->limit * 2 + 10; 
    v->ints = realloc(v->ints, v->limit);  
    } 

    v->ints[v->size] = n; 
    ++v->size; 
} 

int Vector_get(Vector* v, int index) { 
    if(index >= 0 && index < v->size) 
    return v->ints[index]; 

    assert false; 
} 
+0

Cảm ơn bạn, Itay. Tôi sẽ làm theo lời khuyên của bạn. – Dimi

+0

Ví dụ đơn giản tuyệt vời. ('< v-> size()' trong 'Vector_get' không có'() 'Tôi đoán?) – Carl

+0

@Carl - Cảm ơn, Đã sửa lỗi. –

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