Prinsip Desain, Praktik Terbaik dan Pola Desain untuk C (atau Pemrograman Prosedural secara umum)? [Tutup]

92

Adakah prinsip desain, praktik terbaik, dan pola desain yang diketahui yang dapat diikuti seseorang saat merancang proyek C? Atau prinsip desain yang berguna untuk pemrograman prosedural (imperatif) secara umum?

(Saya anak dari 'generasi berorientasi objek' dan harus merancang proyek C besar untuk pertama kalinya)

Dimi
sumber
1
Anda mungkin tertarik dengan pengguna untuk pertanyaan ini: stackoverflow.com/questions/661307/…
mouviciel
7
Saya melakukan beberapa penelitian perpustakaan internet dan universitas, sebelum saya memposting pertanyaan saya, dan jelas tidak kewalahan dengan buku-buku tentang desain perangkat lunak untuk C. Saya meminta favorit Anda (tidak berbicara tentang buku C umum, tidak berbicara tentang konvensi pengkodean seperti variabel yang bermakna nama, tetapi tentang abstraksi yang lebih tinggi, tingkat arsitektur perangkat lunak). Selain itu, saya tidak setuju dengan celaan Anda yang 'bergantung pada orang lain'. Maksud Anda, setiap programmer harus mencari tahu sendiri tentang praktik terbaik dan pola desain yang baik? Ini pasti pertanyaan tentang pengalaman orang lain yang harus digunakan.
Dimi
2
Maaf, Dimi, itu bukan tentang Anda secara khusus, dan saya tidak begitu jelas. Hal ini dulunya diturunkan sebanyak tradisi lisan seperti cara lain: tidak ada set nominal "Pola" resmi, jawaban Jonathon adalah apa yang akan Anda temukan di buku, tetapi semua orang tahu tentang penyembunyian informasi. Tampaknya tradisi lisan sedang hilang, dan banyak programmer muda berpikir bahwa OOP yang menemukan enkapsulasi dan pemisahan. Komunitas ini tampaknya kurang memahami sejarahnya sendiri daripada yang ingin saya lihat. Demikian pengakuan saya bahwa saya berada di wilayah orang tua pemarah.
dmckee --- mantan moderator anak kucing
1
Saya tidak dapat membagikan pandangan retrospektif Anda karena hanya menemukan kaki saya di lapangan, tetapi saya menerima saran Anda. Terima kasih telah mengekspresikan diri Anda dengan lebih jelas, selalu sangat berharga untuk dapat membaca pandangan orang yang berpengalaman. Saya sangat menghargai kontribusi Anda.
Dimi
Standar Pengkodean SEI CERT C menyediakan serangkaian Aturan yang Baik dan praktik umum yang baik serta hal-hal yang harus Anda coba hindari untuk digunakan.
Rami

Jawaban:

65

Menyembunyikan informasi - seperti yang didukung oleh Parnas ( Software Fundamentals ).

Manajemen header dan visibilitas yang cermat:

  • Segala sesuatu di file sumber yang dapat disembunyikan dari dunia luar harus; hanya antarmuka eksternal yang terdokumentasi yang harus diekspos.
  • Segala sesuatu yang diekspos dideklarasikan di header.
  • Header itu digunakan di mana fungsionalitas dibutuhkan (dan di mana ia didefinisikan).
  • Header itu berdiri sendiri - ketika Anda membutuhkannya, Anda menggunakannya, dan Anda tidak perlu khawatir tentang 'header lain apa yang juga harus saya sertakan' karena header memastikannya berfungsi dengan memasukkan apa pun yang diperlukan untuk membuatnya kerja.
  • Header dilindungi sendiri - jadi tidak masalah jika disertakan beberapa kali.

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
    
  • Rancang set fungsi untuk bekerja pada 'objek' (biasanya struktur) - dan gunakan fungsi tersebut daripada melihat-lihat bagian dalam struktur dalam kode yang menggunakannya. Anggap saja sebagai enkapsulasi yang dipaksakan sendiri.

Jonathan Leffler
sumber
Poin yang bagus, terima kasih, Jonathan. Tipe data abstrak adalah contoh bagus lainnya dari penyembunyian informasi dengan pemisahan yang bersih antara penggunaan dan implementasi (antarmuka eksternal yang diketahui dan implementasi internal yang tidak diketahui).
Dimi
23

Tiga saran saya:

  • Tulis tes unit. Mereka akan membantu Anda menemukan desain yang sesuai dengan masalah Anda saat Anda melanjutkan. Jauh lebih baik daripada mengandalkan (hanya) pada pemikiran yang telah dimeditasi sebelumnya.
  • Memiliki detektor kebocoran memori (ada semua jenis pustaka di luar sana) terpasang dan berjalan sejak hari pertama. Mintalah perpustakaan ini mencetak semua kebocoran segera setelah program / tes keluar. Ini akan memungkinkan Anda untuk mengetahui kebocoran segera setelah Anda memasukkannya, sehingga membuat perbaikannya menjadi tidak terlalu menyakitkan.
  • Tulis kode OOP di C. Tidak terlalu sulit. Meskipun dimungkinkan untuk meniru metode penimpaan, saya sarankan Anda mulai dengan emulasi objek sederhana. Bahkan mekanisme sederhana ini dapat memberi Anda jarak tempuh yang luar biasa.

Berikut contohnya:

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;
}
Itay Maman
sumber
Terima kasih, Itay. Saya akan mengikuti saran Anda.
Dimi
1
4. Jangan membuang hasil dari malloc.
SS Anne
22

Ada buku online yang bagus dan gratis, berjudul Pemrograman Berorientasi Objek Dengan ANSI-C , yang membahas topik penulisan kode berorientasi objek di C. Penelusuran Google untuk "C berorientasi objek" juga menghasilkan sejumlah barang lainnya. contoh dan sumber daya.

Jika proyek Anda kritis terhadap keselamatan, MISRA-C adalah seperangkat aturan yang baik. Ini sebagian besar ditujukan untuk c tertanam, tetapi dapat berguna di area lain juga.

Saya menganggap diri saya seorang pembuat kode OO, dan saya melakukan banyak pekerjaan dengan embedded-C. Nasihat terbaik yang bisa saya berikan, terutama untuk proyek-proyek besar, adalah jangan berlebihan. Membuat kerangka kerja OO lengkap di atas ANSI C bisa sangat menggoda, tetapi membutuhkan banyak waktu dan upaya untuk membuatnya benar. Semakin menarik Anda, semakin banyak waktu yang Anda habiskan untuk men-debug kerangka kerja Anda daripada mengerjakan proyek sebenarnya . Dekati tugas dengan pikiran yang jernih, dan pemahaman YAGNI yang baik dan solid . Semoga berhasil!

e. James
sumber
Terima kasih, e.James. Saya tidak ingin membuat kerangka kerja berorientasi objek di atas ANSI C, tetapi mencari prinsip desain pemrograman prosedural khusus dan sesuai. Petunjuk MISRA-C sangat berguna, terutama karena ini sebenarnya adalah proyek yang disematkan. Saya akan melihatnya lebih dekat.
Dimi
Ah, nikmatnya C. Jangan lupa bahwa Anda harus mendeklarasikan variabel Anda di bagian atas fungsi Anda (atau di bagian atas { }blok mana pun ). Yang satu itu selalu menggigitku sekali atau dua kali:)
e. James
6

OOP adalah metodologi bukan teknologi. Jadi saran pertama saya adalah berhenti menganggapnya sebagai pemrograman prosedural.

Untuk poin e.James, Anda tidak ingin mencoba dan menciptakan kembali bahasa berorientasi objek atau berpura-pura bahwa Anda memiliki kemampuannya. Anda masih dapat melakukan semua hal yang benar dengan berpegang pada beberapa prinsip sederhana:

  1. Uji coba semuanya.
  2. Temukan apa yang memvariasikan dan merangkumnya.
  3. Desain antarmuka.

sumber