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)? [đóng cửa]


91

Có bất kỳ nguyên tắc thiết kế nào đã biết, các phương pháp hay nhất và các mẫu thiết kế mà người ta có thể tuân theo 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 (mệnh lệnh) nói chung?

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


1
Bạn có thể quan tâm anwsers cho câu hỏi này: stackoverflow.com/questions/661307/...
mouviciel

7
Tôi đã thực hiện một số nghiên cứu trên Internet và thư viện trường đại học, trước khi tôi đăng câu hỏi của mình và chắc chắn không bị choáng ngợp với những cuốn sách về thiết kế phần mềm cho C. Tôi hỏi bạn về cuốn sách yêu thích của bạn (không nói về sách C chung, không nói về quy ước mã hóa như biến có nghĩa tên, nhưng về mức độ trừu tượng cao hơn, kiến ​​trúc phần mềm). Hơn nữa, tôi không đồng ý với lời trách móc 'dựa dẫm vào người khác' của bạn. Ý bạn 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 chắc chắn là một câu hỏi về kinh nghiệm của người khác phải được sử dụng.
Dimi

2
Xin lỗi, Dimi, đó không phải là về bạn nói riêng và tôi không rõ lắm. Điều này từng được truyền miệng nhiều như bất kỳ cách nào khác: không có một bộ danh nghĩa chính thức về "Mẫu", câu trả lời của Jonathon là những gì bạn tìm thấy trong sách, nhưng mọi người đều biết về việc che giấu thông tin. Có vẻ như truyền thống truyền miệng đang bị mất, và nhiều lập trình viên trẻ tuổi nghĩ rằng OOP đã phát minh ra tính năng đóng gói và phân tách. Cộng đồng này dường như có ít cảm giác về lịch sử của chính nó hơn tôi muốn thấy. Vì vậy, sự thừa nhận của tôi rằng tôi đang ở trong lãnh thổ của một ông già khó tính.
dmckee --- ex-moderator kitten.

1
Tôi không thể chia sẻ quan điểm hồi tưởng của bạn vì chỉ cần tìm thấy đôi chân của tôi trong lĩnh vực này, nhưng tôi chấp nhận đề xuất của bạn. Cảm ơn bạn đã thể hiện bản thân rõ ràng hơn, luôn có giá trị lớn để nhận được cách nhìn của một người từng trải. Tôi thực sự đánh giá cao sự đóng góp của bạn.
Dimi

Tiêu chuẩn mã hóa CERT của SEI cung cấp bộ Quy tắc tốt và Thực hành tốt thường gặp cũng như những điều bạn nên tránh sử dụng.
Rami

Câu trả lời:


65

Che giấu thông tin - theo sự tán thành của Parnas ( Phần mềm Cơ bản ).

Quản lý cẩn thận các tiêu đề và khả năng hiển thị:

  • Mọi thứ trong một tệp nguồn có thể được ẩn khỏi thế giới bên ngoài nên được; chỉ giao diện bên ngoài được lập thành văn bản mới được để lộ.
  • Mọi thứ lộ ra đều được khai báo trong tiêu đề.
  • Tiêu đề đó được sử dụng khi chức năng cần thiết (và nơi nó được xác định).
  • Tiêu đề là độc lập - khi bạn cần, bạn sẽ sử dụng nó và bạn không phải băn khoăn về việc 'tôi cũng phải bao gồm những tiêu đề nào khác' bởi vì tiêu đề đảm bảo nó hoạt động bằng cách bao gồm bất kỳ thứ gì cần thiết để tạo ra nó. công việc.
  • Tiêu đề được tự bảo vệ - vì vậy không quan trọng nếu nó được đưa vào 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 */
  • Thiết kế tập hợp các chức năng để hoạt động trên 'đối tượng' (thường là cấu trúc) - và sử dụng các chức năng đó thay vì xem xét các phần bên trong của cấu trúc trong mã đang sử dụng nó. Hãy coi đó là sự đóng gói tự áp đặt.


Đ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ụ điển hình khác về việc ẩn thông tin với sự tách biệt rõ ràng giữa việc sử dụng và triển khai (giao diện bên ngoài đã biết và triển khai bên trong chưa biết).
Dimi

23

Ba lời khuyên của tôi:

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

Đây là một ví dụ:

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

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;
}

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

1
4. Không bỏ kết quả của malloc.
SS Anne

22

Có một cuốn sách trực tuyến hay, miễn phí, có tựa đề Lập trình hướng đối tượng Với ANSI-C , bao gồm chủ đề viết mã hướng đối tượng trong C. Một tìm kiếm trên google cho "hướng đối tượng C" cũng mang lại một số nội dung hay khác ví dụ và tài nguyên.

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

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


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 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. Gợi ý MISRA-C rất hữu ích, đặc biệt vì nó thực sự là một dự án nhúng. Tôi sẽ xem xét kỹ hơn nó.
Dimi

À, niềm vui khi được nhúng C. Đừng quên rằng bạn phải khai báo các biến ở đầu hàm (hoặc ở đầu bất kỳ { }khối nào ). Con đó luôn cắn tôi một hoặc hai lần:)
e.James

7

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

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

  1. Lái thử mọi thứ.
  2. Tìm những gì khác nhau và đóng gói nó.
  3. Thiết kế giao diện.
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.