Tcopen: Konvensi

Dibuat pada 30 Okt 2020  ·  31Komentar  ·  Sumber: TcOpenGroup/TcOpen

Dokumen konvensi di sini

Silakan berkontribusi untuk diskusi di bawah ini

  • Mari kita lanjutkan diskusi di sini untuk pelacakan.
  • Obrolan cepat di sini:TcOpen Slack

  • [ ] Konvensi penamaan untuk variabel (VAR, VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, VAR_INST, TEMP)

  • [ ] Konvensi penamaan untuk metode
  • [ ] Konvensi penamaan untuk properti
  • [ ] Konvensi penamaan untuk blok (FB, FC, PRG, dll.)
discussion

Komentar yang paling membantu

Saya akan memiliki saran tentang array. Ada persyaratan formal untuk kompiler inxton yang mentrans-tumpuk hanya array yang berbasis 0. Alasannya adalah untuk mencegah kebingungan saat digunakan di C#.

_array : ARRAY[0..10] DARI BOOL; // trans-tumpukan
ketika
_array : ARRAY[1..10] DARI BOOL; // tidak melakukan trans-tumpukan

Ada komentar tentang ini?

Semua 31 komentar

@mark-lazarides @Roald87 @philippleidig @jozefchmelar mari kita lanjutkan diskusi tentang konvensi di sini... kendur untuk obrolan singkat; diskusi di sini untuk melacak aktivitas

  • Menurut pendapat saya, properti harus didefinisikan sebagai berikut "IsEnabled". Nama itu sendiri seharusnya sudah menunjukkan jenisnya.

  • Saya suka nilai pengembalian metode sebagai boolean. Saya menemukan tipe data yang lebih kompleks tidak pantas, karena mereka harus dipakai di luar atau dikembalikan dengan referensi.

  • Warisan dari setiap kelas dasar "fbComponent" diperlukan untuk menggunakan Inxton atau tc.prober?

  • Ketika datang ke penamaan jenis, saya pribadi agak radikal dan umumnya meninggalkan awalan. Kecuali untuk antarmuka, referensi, dan pointer.
    misalnya

    Jenis Penamaan


| Jenis blok | Notasi | Awalan | Contoh |
| :------------- | :--------- | :------------ | :------------------------------------------------- -- |
| Nama FB/Kelas | PascalCase |Tidak | Cyclinder |
| nama jenis ENUM | PascalCase |Tidak | MachineState.Start |
| Nama ANTARMUKA | PascalCase | I | ICyclinder |
| Nama FUNGSI | PascalCase |Tidak | Add() |
| Nama STRUKTUR | PascalCase | Tidak | Data |
| Nama UNION | PascalCase | Tidak | Control |

@philippleidig

  • Menurut pendapat saya, properti harus didefinisikan sebagai berikut "IsEnabled". Nama itu sendiri seharusnya sudah menunjukkan jenisnya.

Sangat setuju.

  • Saya suka nilai pengembalian metode sebagai boolean. Saya menemukan tipe data yang lebih kompleks tidak pantas, karena mereka harus dipakai di luar atau dikembalikan dengan referensi.

Kami menggunakannya seperti yang dijelaskan dengan komponen kami. Hal ini berguna ketika mengontrol keadaan suatu urutan. Dalam sebagian besar kasus, cukup bool. Terkadang akan menyenangkan untuk memiliki lebih banyak informasi tentang status metode ... tetapi ini perlu diskusi yang lebih luas (mungkin sintaksis lancar seperti sesuatu)

  • Warisan dari setiap kelas dasar "fbComponent" diperlukan untuk menggunakan Inxton atau tc.prober?

Tidak. Tidak ada persyaratan khusus untuk itu atau Inxton atau tc.prober. Kami menggunakannya dengan cara ini. ComponentBase adalah kelas abstrak yang memiliki beberapa kontrak publik (Metode Manual, dll), tetapi dapat mengimplementasikan beberapa fitur umum untuk komponen. Saya bukan penggemar berat warisan (saya lebih suka komposisi), tetapi dalam hal ini saya ingin membuka beberapa opsi untuk masa depan.

Di inxton jika Anda ingin mengumpulkan semua komponen dalam koleksi, Anda dapat melakukannya ketika something is copmonent ada mekanisme untuk itu.

Ada juga alasan lain untuk itu. Kami bekerja hari ini pada open-source perpustakaan dasar kami, yang memiliki beberapa persyaratan dalam hal. Saya berharap akan dapat menemukan sesuatu minggu depan. Untuk memberi Anda lebih banyak detail.

  • Ketika datang ke penamaan jenis, saya pribadi agak radikal dan umumnya meninggalkan awalan. Kecuali untuk antarmuka, referensi, dan pointer.
    misalnya

Jenis Penamaan

Contoh Awalan Notasi tipe blok
Nama FB/CLASS PascalCase No Cyclinder
ENUM ketik nama PascalCase No MachineState.Start
Nama INTERFACE PascalCase I ICyclinder
Nama FUNGSI PascalCase No Add()
STRUCT nama PascalCase No Data
Nama UNION PascalCase No Control

Bukan penggemar awalan juga. Tabel tersebut menyerupai sistem awalan yang kita gunakan... tetapi sekali lagi kita memutuskan untuk menyingkirkannya, itu akan membuat saya senang.

Dalam kebanyakan kasus saya tidak melihat manfaat dalam menggunakan awalan. Saya setuju dengan proposal @philippleidig .

Saya akan mengatakan bahwa pointer dan referensi adalah pengecualian di sini.

Saya mengusulkan konvensi saya di PR # 5

Penamaan Anggota & Penamaan Jenis

Saya tidak melihat manfaat dalam menggunakan awalan. Itu tidak membantu saya dengan cara apapun.

Variabel Anggota

Variabel anggota kelas (FB) harus disembunyikan dan dimulai dengan nama kecil
~PascalVAR{atribut 'sembunyikan'}pemicu: BOOL;{atribut 'sembunyikan'}penghitung : INT;{atribut 'sembunyikan'}analogStatus : AnalogStatus;END_VAR~

@jozefchmelar

Dalam kebanyakan kasus saya tidak melihat manfaat dalam menggunakan awalan. Saya setuju dengan proposal @philippleidig .

Saya akan mengatakan bahwa pointer dan referensi adalah pengecualian di sini.
👍
Saya mengusulkan konvensi saya di PR # 5

Penamaan Anggota & Penamaan Jenis

Saya tidak melihat manfaat dalam menggunakan awalan. Itu tidak membantu saya dengan cara apapun.
👍👍

Variabel Anggota

Variabel anggota kelas (FB) harus disembunyikan dan dimulai dengan nama kecil

    VAR
        {attribute 'hide'}
        trigger : BOOL;
        {attribute 'hide'}
        counter : INT;
        {attribute 'hide'}
        analogStatus : AnalogStatus;
    END_VAR
  • variabel tersembunyi tidak akan terlihat di atas iklan sehingga jika tidak diperlukan di HMI, variabel tersebut dapat disembunyikan. Tetapi jika kita perlu melihatnya di HMI, kita tidak boleh menggunakan atribut 'sembunyikan'.
  • Tc3 tidak peka huruf besar/kecil sehingga trigger (nama variabel) dan Trigger (nama properti) akan bentrok. Kita perlu mengawalinya dengan _ seperti yang saya kira

Setuju sekali 👍

Ada juga atribut "pertunjukan bersyarat". Tetapi ini hanya dapat digunakan bersama dengan perpustakaan yang dikompilasi.
https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/8095402123.html &id=7685156034373049758
Karena saya berasumsi bahwa kami akan menyediakan perpustakaan terbuka, ini hanya masuk akal.

_ sebagai awalan untuk variabel anggota diperlukan seperti yang dikatakan @PTKu .

Saya biasanya suka mengikuti konvensi penamaan dan pemilihan nama C#.

Saya suka nilai pengembalian metode sebagai boolean. Saya menemukan tipe data yang lebih kompleks tidak pantas, karena mereka harus dipakai di luar atau dikembalikan dengan referensi.

@philippleidig apa yang Anda maksud dengan nilai balik? Dalam hal ini mereka digunakan sebagai pemeriksaan kesalahan? Biasanya nilai pengembalian tergantung pada metode. CalculcateArea akan mengembalikan REAL `LREAL`.

Sepenuhnya setuju pada penamaan variabel yang disarankan!

Saya suka nilai pengembalian metode sebagai boolean. Saya menemukan tipe data yang lebih kompleks tidak pantas, karena mereka harus dipakai di luar atau dikembalikan dengan referensi.

@philippleidig apa yang Anda maksud dengan nilai balik? Dalam hal ini mereka digunakan sebagai pemeriksaan kesalahan? Biasanya nilai pengembalian tergantung pada metode. CalculcateArea akan mengembalikan REAL``LREAL .

@Roald87 idenya adalah metode komponen yang melakukan tindakan akan mengembalikan 'benar' ketika tindakan selesai (MoveToHome() saat sensor/posisi rumah tercapai). Ini tidak mencegah jenis pengembalian lainnya bila diperlukan.

Sepenuhnya setuju pada penamaan variabel yang disarankan!

Saya akan memiliki saran tentang array. Ada persyaratan formal untuk kompiler inxton yang mentrans-tumpuk hanya array yang berbasis 0. Alasannya adalah untuk mencegah kebingungan saat digunakan di C#.

_array : ARRAY[0..10] DARI BOOL; // trans-tumpukan
ketika
_array : ARRAY[1..10] DARI BOOL; // tidak melakukan trans-tumpukan

Ada komentar tentang ini?

Sama untuk TwinCAT HMI (TE2000)

Sama untuk TwinCAT HMI (TE2000)

Akan sangat nyaman untuk menyelaraskan array dengan HMI!

@philippleidig || @Roald87 apakah salah satu dari Anda akan mengadakan konvensi PR tentang array, lalu tolong... Saya hanya suka melihat lebih banyak kontributor di repo :).

Saya akan memiliki saran tentang array. Ada persyaratan formal untuk kompiler inxton yang mentrans-tumpuk hanya array yang berbasis 0. Alasannya adalah untuk mencegah kebingungan saat digunakan di C#.

_array : ARRAY[0..10] DARI BOOL; // trans-tumpukan
ketika
_array : ARRAY[1..10] DARI BOOL; // tidak melakukan trans-tumpukan

Ada komentar tentang ini?

Karena cara kerja perulangan teks terstruktur, saya lebih suka menjaga array PLC berdimensi 1..X. Hasilnya, kode lebih mudah dibaca di mana saja di PLC. Saya pikir kita harus selalu menulis kode yang menarik dan dapat dipelihara di PLC. Jika kita membutuhkan shim untuk membuatnya bekerja lebih baik pada bit kode pihak ketiga, kita dapat mengelolanya secara terpisah.

// Declaration
NUMBER_OF_DRIVES : INT := 10;
drives  : ARRAY[1..NUMBER_OF_DRIVES] OF I_Drive;

// now in the code
FOR i := 1 to NUMBER_OF_DRIVES DO
   drives[i].SomethingCool();
END_FOR

// Compared to

// Declaration
drives : ARRAY[0..(NUMBER_OF_DRIVES -1) ] OF I_Drive;
// Code
FOR i := 0 to (NUMBER_OF_DRIVES -1) DO
   drives[i].SomethingCool();
END_FOR

Saya suka nilai pengembalian metode sebagai boolean. Saya menemukan tipe data yang lebih kompleks tidak pantas, karena mereka harus dipakai di luar atau dikembalikan dengan referensi.

Saya pikir metode harus mengembalikan apa pun yang masuk akal untuk metode tersebut. Nama metode akan membantu Anda memahaminya.

yaitu

IF NOT piece.PassesValidation() THEN
 LogError('Piece does not pass validation');
END_IF

// OR

IF sequence.Finished THEN
  axis.Disable(); // No return type necessary.
  state := WaitForAxisDisabled;
END_IF

@Roald87 idenya adalah metode komponen yang melakukan tindakan akan mengembalikan 'benar' ketika tindakan selesai (MoveToHome() saat sensor/posisi rumah tercapai). Ini tidak mencegah jenis pengembalian lainnya bila diperlukan.

Saya benar-benar tidak suka pendekatan berulang kali memanggil metode publik, di mana metode itu menjalankan fungsi berulang kali hingga kembali benar. Ada satu kasus yang menurut saya dapat diterima (jika ada metode tipe "Jalankan" pada antarmuka, tetapi ada juga cara yang lebih baik untuk itu, saya percaya).

Masalah dengan itu;

  • Anda dapat/ sedang membuat jalur eksekusi pada kelas yang dapat dipanggil secara bersamaan. Yaitu
atEnd :=  axis.GoToEnd();
atBeginning := axis.GoToBeginning();
  • Kelas harus mengelola status mereka secara internal. Metode dapat digunakan untuk membuat permintaan dan modifikasi dari dan ke status tersebut, dan properti dapat digunakan untuk mengakses status atau menyetel status sederhana juga.
  • Bagaimana Anda memberi nama metode itu sehingga jelas bagaimana dan mengapa metode itu digunakan dengan cara itu? axis.GoToEndTrueWhenComplete()?
  • Bagaimana jika keadaan dasar kelas berubah dengan cara yang mengubah cara panggilan itu dijalankan?
  • Kondisi balapan bisa lebih mudah dihasilkan. Jika kita berulang kali memanggil .Enable() pada sesuatu, tetapi kita mendapatkan kesalahan untuk pemindaian tunggal, maka .Enable() mungkin tetap Mengaktifkan menggunakan pendekatan "lanjutkan panggilan hingga selesai". Ini seharusnya .RequestEnable : BOOL, yang menunjukkan apakah kondisi yang mendasari pada titik permintaan sudah benar (memungkinkan kode panggilan untuk mundur dengan anggun pada titik itu). Jika permintaan dapat dibuat, kode panggilan kemudian dapat memantau .IsEnabled dan .InError untuk penyelesaian.

@philippleidig tidak akrab dengan TwinCAT HMI. Bagaimana array berbasis non 0 ditangani di sana?

@mark-lazarides

Saya pikir metode harus mengembalikan apa pun yang masuk akal untuk metode tersebut. Nama metode akan membantu Anda memahaminya.
👍

Concurrency dan kondisi balapan adalah masalah yang masuk akal. IMHO Masalah-masalah ini harus diatasi sebanyak mungkin di tingkat komponen, tetapi yang lebih penting di tingkat koordinasi saat mengonsumsi komponen. Metode komponen harus dipanggil dari dalam primitif seperti pengontrol keadaan yang diimplementasikan dengan benar (baik itu CASE sederhana, IF, ELSIF, atau sequencer/selector/iterator yang lebih kompleks) yang akan mencegah panggilan bersamaan dari metode yang bertentangan dari instance komponen yang sama .

Sesuatu seperti ini harus dicegah dalam kode konsumen komponen
~atEnd := axis.GoToEnd();atBeginning := axis.GoToBeginning();~

executing methods mengembalikan true setelah selesai memungkinkan penggunaan deklaratif yang bersih.

Apa yang ada dalam pikiran saya adalah sesuatu seperti ini:

~~~
VAR
_status : INT;

END_VAR

KASUS _status
0:
JIKA(sumbu.MoveAbsolute(Posisi: 100.0)) MAKA
_status := 1;
BERAKHIR JIKA;
1:
JIKA(axis.MoveRelative(Posisi: 100.0)) MAKA
_status := 2;
BERAKHIR JIKA;
2:
JIKA(sumbu.MoveAbsolute(Posisi: 300.0)) MAKA
_status := 3;
BERAKHIR JIKA;
3:
_status := 0;
END_CASE
~~~

Ini dapat dikurangi menjadi

~~~
VAR
_status : INT;

END_VAR

KASUS _status
0:
Menunggu(axis.MoveAbsolute(Posisi: 100.0),1);
1:
Menunggu(axis.MoveRelative(Posisi: 100.0),2);
2:
Menunggu(axis.MoveAbsolute(Posisi: 300.0),3);
3:
Tunggu(benar,0);

END_CASE

=====================================

METODE Menunggu
VAR_INPUT
selesai : BOOL
nextState : INT;
END_VAR
JIKA (selesai) MAKA
_status := status berikutnya;

BERAKHIR JIKA;

~~~
edit: Saya berasumsi bahwa komponen tersebut digunakan dalam tugas plc tunggal

Ini menempatkan batasan pada penggunaan kode. Komponen kami tidak bertanggung jawab atas kesalahan jika konsumen menggunakannya dalam urutan yang salah. Mereka harus merespons dengan baik semua interaksi. Mereka tidak perlu "berfungsi" (yaitu memanggil res := axis.MoveTo(Position:=100); sebelum axis.Enable() tidak akan berfungsi), tetapi kode yang dikonsumsi harus diberikan informasi yang cukup di semua titik untuk memahami di mana masalahnya.

Itu masih tidak terbaca dengan baik untukku juga. Anda tidak dapat membaca axis.MoveAbsolute(syx) dan memahaminya perlu dipanggil secara siklis. Anda hanya akan mengerti bahwa jika Anda tahu bahwa gaya idiomatik kami mengharuskan Anda dan pada saat itu saya pikir kami telah gagal dalam menciptakan sesuatu yang sangat berguna.

Saya juga akan mengatakan, bahwa terlepas dari apakah kesalahan dapat diperhitungkan, mereka masih lebih mungkin. Dengan pendekatan pemanggilan metode siklis, Anda dapat membuat metode yang memeriksa apakah status objek siap dipanggil, lalu memanggil metode siklis, lalu memantau status objek lainnya untuk memastikan tidak ada yang terjadi untuk sementara. Atau Anda membuat permintaan, yang memberi tahu Anda apakah itu berhasil atau tidak, kemudian memantau status penyelesaiannya. Anda dapat mendaftarkan panggilan balik untuk itu sebagai bagian dari permintaan jika Anda mau, yang merupakan pendekatan OO yang layak untuk ini dan mengurangi lebih banyak panggilan/interogasi secara siklis.

@mark-lazarides benar! Saya execute methods (sebut saja mereka seperti itu) tidak boleh mengimplementasikan logika siklik. Saya berasumsi apa yang telah kita diskusikan sebelumnya bahwa kita memastikan bahwa apa yang perlu dieksekusi secara siklis akan ditempatkan baik di badan FB atau dalam metode Cyclic ; yang harus dipanggil di beberapa tempat yang tepat dalam program konsumen.

OKE. Jadi mengapa kita memanggil metode ini secara siklis? Saya masih berpikir argumen asli tetap berlaku. Metode harus melakukan satu pekerjaan. Mulai sesuatu (dan karena itu laporkan keberhasilannya) atau dapatkan sesuatu (dan kembalikan).

OKE. Jadi mengapa kita memanggil metode ini secara siklis? Saya masih berpikir argumen asli tetap berlaku. Metode harus melakukan satu pekerjaan. Mulai sesuatu (dan karena itu laporkan keberhasilannya) atau dapatkan sesuatu (dan kembalikan).

Tidak keberatan Mark, kita tidak perlu memanggil metode eksekusi secara siklis, tetapi seharusnya tidak menjadi masalah jika kita melakukannya.

Saya tidak mengerti mengapa suatu metode tidak dapat mengembalikan hasil operasi.

Saya pikir kita harus membuat beberapa komponen yang lebih kompleks dan membuat prototipe ide-ide ini (piston pneumatik tidak cukup rumit untuk diskusi ini) Saya pikir kita bisa mulai dengan penggerak/sumbu.

Setuju, Petrus.

Karena nama utasnya, saya pikir kami bertujuan untuk ini sebagai konvensi! Mohon maaf jika saya salah paham.

Chris memiliki blok sumbu dasar sebagai PR saat ini - saya telah mengomentarinya, tetapi perlu lebih banyak perhatian.

@mark-lazarides tidak perlu meminta maaf Mark, kami di sini untuk berdiskusi dengan bebas, saya akan melihat PR besok ...

@philippleidig @Roald87 @dhullett08 Diskusi tentang desain komponen juga di sini

Beberapa saran acak diambil dari dokumen PLCopen.

plcopen_coding_guidelines_version_1.0.pdf

Konstanta
Harus dalam ALLCAPS sehingga mudah dikenali

Panjang Nama yang Dapat Diterima
Minimal 4 karakter maksimal 24 karakter?

Beberapa saran acak diambil dari dokumen PLCopen.

plcopen_coding_guidelines_version_1.0.pdf

Terima kasih untuk tautannya

Konstanta
Harus dalam ALLCAPS sehingga mudah dikenali

👍

Panjang Nama yang Dapat Diterima
Minimal 4 karakter maksimal 24 karakter?

Nama yang lebih panjang seharusnya tidak menjadi masalah sampai mereka mengungkapkan maksudnya, 24 karakter sudah cukup, namun saya tidak akan membatasi maks. karakter. Nama yang terlalu pendek memang mencurigakan, seharusnya lebih dari 4 karakter.

@Seversonic komentar Anda ditambahkan ke dokumen...

lanjutan diskusi di sini #11

Saya benar-benar tidak menyukai Konvensi Anda tetapi saya pikir Proyek Anda cukup menarik!
secara pribadi saya lebih suka cara yang lebih klasik
Blok fungsi FB_ fb
M_Add() Metode
P_Parameter Prop

Hai, @PeterZerlauth dan terima kasih. Agak sulit untuk menyetujui konvensi karena kita berada di tengah jalan antara PLC dan rekayasa perangkat lunak klasik.

Berikut polling dari awal diskusi:

TcOpen.Survey.Result.pdf

Selain itu, ada diskusi di sini dan di Slack Channel, mungkin ada juga di repo @dhullett08 TcOpen.

Ada perasaan umum (atau setidaknya saya menafsirkannya seperti itu) bahwa kita harus meninggalkan awalan jika mereka tidak memberikan informasi yang berguna atau IDE modern memberikan informasi yang kami sampaikan dengan awalan di masa lalu.

Saya mengerti ini tentang preferensi pribadi dan benar-benar tidak ada cara yang benar atau salah untuk melakukannya. Hanya saja kita harus menyetujui sesuatu.

Menutup di sini diskusi berlanjut di sini: https://github.com/TcOpenGroup/TcOpen/discussions/11

Apakah halaman ini membantu?
0 / 5 - 0 peringkat