Bagaimana memulihkan dari kerusakan mesin-kondisi-terbatas?

13

Pertanyaan saya mungkin tampak sangat ilmiah tetapi saya pikir ini adalah masalah umum dan pengembang dan programmer berpengalaman mudah-mudahan akan memiliki beberapa saran untuk menghindari masalah yang saya sebutkan dalam judul. Btw., Apa yang saya jelaskan di bawah adalah masalah nyata yang saya coba selesaikan secara proaktif dalam proyek iOS saya, saya ingin menghindarinya dengan cara apa pun.

Dengan mesin negara yang terbatas maksud saya> Saya memiliki UI dengan beberapa tombol, beberapa sesi menyatakan relevan dengan UI itu dan apa yang diwakili UI ini, saya memiliki beberapa data yang nilainya sebagian ditampilkan di UI, saya menerima dan menangani beberapa pemicu eksternal. (diwakili oleh panggilan balik dari sensor). Saya membuat diagram keadaan untuk memetakan skenario yang relevan yang diinginkan dan dapat diubah dengan lebih baik dalam UI dan aplikasi tersebut. Ketika saya perlahan-lahan menerapkan kode, aplikasi mulai berperilaku lebih dan lebih seperti seharusnya. Namun, saya tidak terlalu yakin bahwa itu cukup kuat. Keraguan saya datang dari menonton pemikiran saya sendiri dan proses implementasi. Saya yakin bahwa saya sudah membahas semuanya, tetapi cukup untuk melakukan beberapa tes kasar di UI dan saya segera menyadari bahwa masih ada kesenjangan dalam perilaku. Saya menambalnya. Namun, karena setiap komponen tergantung dan berperilaku berdasarkan input dari beberapa komponen lain, input tertentu dari pengguna atau beberapa sumber eksternal memicu serangkaian peristiwa, menyatakan perubahan..etc. Saya memiliki beberapa komponen dan masing-masing berperilaku seperti ini Pemicu yang diterima pada input -> trigger dan pengirimnya dianalisis -> output sesuatu (pesan, perubahan status) berdasarkan analisis

Masalahnya adalah, ini tidak sepenuhnya mandiri, dan komponen saya (item basis data, status sesi, status beberapa tombol) ... BISA diubah, dipengaruhi, dihapus, atau dimodifikasi, di luar ruang lingkup rantai peristiwa atau skenario yang diinginkan. (ponsel crash, baterai ponsel kosong tiba-tiba) Ini akan memperkenalkan situasi tidak valid ke dalam sistem, dari mana sistem berpotensi TIDAK BISA MAMPU memulihkan. Saya melihat ini (walaupun orang tidak menyadari ini masalahnya) di banyak aplikasi pesaing saya yang ada di toko apel, pelanggan menulis hal-hal seperti ini> "Saya menambahkan tiga dokumen, dan setelah pergi ke sana-sini, saya tidak bisa membukanya, bahkan jika melihat mereka. " atau "Saya merekam video setiap hari, tetapi setelah merekam video yang terlalu masuk, saya tidak dapat mengubah takaririnya .., dan tombol untuk takarir tidak

Ini hanya contoh singkat, pelanggan sering menggambarkannya lebih detail..dari deskripsi dan perilaku yang dijelaskan di dalamnya, saya berasumsi bahwa aplikasi tertentu memiliki gangguan FSM.

Jadi pertanyaan utamanya adalah bagaimana saya bisa menghindari ini, dan bagaimana melindungi sistem dari pemblokiran itu sendiri?

EDIT> Saya berbicara dalam konteks pandangan satu viewcontroller di telepon, maksud saya satu bagian dari aplikasi. Saya Memahami pola MVC, saya memiliki modul terpisah untuk fungsi yang berbeda .. semua yang saya jelaskan relevan dengan satu kanvas di UI.

Earl Grey
sumber
2
Kedengarannya seperti kasing untuk unit test!
Michael K

Jawaban:

7

Saya yakin Anda sudah mengetahui hal ini tetapi untuk berjaga-jaga:

  1. Pastikan setiap node dalam diagram keadaan memiliki busur keluar untuk SETIAP jenis input hukum (atau bagi input menjadi kelas, dengan satu busur keluar untuk setiap kelas input).

    Setiap contoh saya telah melihat mesin negara hanya menggunakan satu busur keluar untuk input salah APAPUN.

    Jika tidak ada jawaban yang pasti tentang apa yang akan dilakukan input setiap waktu, itu adalah kondisi kesalahan, atau ada input lain yang hilang (yang secara konsisten akan menghasilkan lengkungan untuk input yang menuju ke simpul baru).

    Jika sebuah node tidak memiliki lengkungan untuk satu jenis input, maka itu adalah asumsi input tidak akan pernah terjadi dalam kehidupan nyata (ini adalah kondisi kesalahan potensial yang tidak akan ditangani oleh mesin negara).

  2. Pastikan mesin keadaan hanya dapat mengambil atau mengikuti hanya satu busur sebagai respons terhadap input yang diterima (tidak lebih dari satu busur).

    Jika ada berbagai jenis skenario kesalahan, atau jenis input yang tidak dapat diidentifikasi pada waktu desain mesin negara, skenario kesalahan dan input yang tidak diketahui harus melengkung ke keadaan dengan jalur yang sepenuhnya terpisah terpisah dari "busur normal".

    Yaitu jika kesalahan atau tidak dikenal diterima dalam keadaan "dikenal", maka busur diikuti sebagai hasil dari penanganan kesalahan / input tidak dikenal tidak boleh kembali ke keadaan apa pun mesin akan berada di jika hanya menerima input yang dikenal.

  3. Setelah Anda mencapai status terminal (akhir), Anda seharusnya tidak dapat kembali ke non-terminal hanya ke status awal (awal).

  4. Untuk satu mesin keadaan seharusnya tidak boleh lebih dari satu keadaan awal atau awal (berdasarkan contoh yang saya lihat).

  5. Berdasarkan apa yang saya lihat satu mesin negara hanya dapat mewakili keadaan satu masalah atau skenario.
    Seharusnya tidak pernah ada beberapa status yang mungkin pada satu waktu dalam satu diagram keadaan.
    Jika saya melihat potensi beberapa keadaan konkuren, ini memberitahu saya bahwa saya perlu membagi diagram keadaan menjadi 2 atau lebih mesin keadaan terpisah yang memiliki potensi masing-masing negara untuk dimodifikasi secara independen.

AB
sumber
9

Maksud dari mesin keadaan terbatas adalah bahwa ia memiliki aturan eksplisit untuk segala sesuatu yang dapat terjadi dalam suatu keadaan. Itu sebabnya terbatas .

Contohnya:

if a:
  print a
elif b:
  print b

Apakah tidak terbatas, karena kita bisa mendapatkan masukan c. Ini:

if a:
  print a
elif b:
  print b
else:
  print error

terbatas, karena semua input yang mungkin diperhitungkan. Ini memperhitungkan kemungkinan input ke keadaan , yang mungkin terpisah dari pengecekan kesalahan. Bayangkan mesin negara dengan status berikut:

No money state. 
Not enough money state.
Pick soda state.

Di dalam negara yang ditentukan, semua input yang mungkin ditangani untuk memasukkan uang dan soda dipilih. Kegagalan daya berada di luar mesin negara, dan "tidak ada". Mesin status hanya dapat menangani input untuk status yang dimilikinya, sehingga Anda memiliki dua pilihan.

  1. Menjamin bahwa semua tindakan adalah atom. Mesin dapat kehilangan daya total dan masih membiarkan semuanya dalam keadaan stabil dan benar.
  2. Perluas status Anda untuk memasukkan masalah yang tidak diketahui, dan ada kesalahan yang menendang Anda ke status ini, tempat masalah ditangani.

Untuk referensi, artikel wiki pada mesin negara teliti. Saya juga menyarankan Code Complete , untuk bab-bab tentang membangun perangkat lunak yang stabil dan dapat diandalkan.

Spencer Rathbun
sumber
"Kita bisa mendapatkan input c" - inilah mengapa bahasa-bahasa yang aman untuk mengetik sangat penting. Jika tipe input Anda adalah bool, Anda bisa mendapatkan truedan false, tetapi tidak ada yang lain. Meskipun begitu, penting untuk memahami tipe Anda - mis. Tipe yang dapat NaN
dibatalkan
5

Ekspresi reguler diimplementasikan sebagai mesin keadaan terbatas. Tabel transisi yang dihasilkan oleh kode pustaka akan memiliki status kegagalan bawaan, untuk menangani apa yang terjadi jika input tidak cocok dengan pola. Setidaknya ada transisi implisit ke keadaan gagal dari hampir setiap negara lain.

Tata bahasa bahasa pemrograman bukan FSM, tetapi generator parser (seperti Yacc atau bison) umumnya memiliki cara untuk memasukkan satu atau beberapa status kesalahan, sehingga input yang tidak terduga dapat menyebabkan kode yang dihasilkan berakhir dalam keadaan kesalahan.

Kedengarannya seperti FSM Anda memerlukan status kesalahan atau kegagalan atau setara moral, bersama dengan transisi eksplisit (untuk kasus yang Anda antisipasi) dan implisit (untuk kasus yang tidak Anda antisipasi) ke salah satu status kegagalan atau kesalahan.

Bruce Ediger
sumber
Maafkan saya, jika pertanyaan saya terdengar konyol, karena saya tidak memiliki pendidikan formal di CS, dan saya hanya belajar pemrograman selama beberapa bulan. Apakah itu berarti, bahwa, ketika saya membiarkan mengatakan metode handler, untuk acara push untuk sebuah tombol, dan dalam metode itu saya memiliki struktur if-else-switch-conditioning yang cukup rumit (20-30 baris kode), yang Saya harus selalu menangani input yang tidak diinginkan secara eksplisit? ATAU maksud Anda pada level "global"? Haruskah saya memiliki kelas terpisah menonton FSM ini, dan ketika masalah terjadi, itu akan mengatur ulang nilai dan status?
Earl Grey
Menjelaskan parser yang dihasilkan Yacc atau Bison ada di luar jangkauan saya, tetapi biasanya, Anda menangani kasus-kasus yang diketahui, dan kemudian memiliki blok kode kecil untuk "segalanya berjalan ke status kesalahan atau kegagalan". Kode untuk status kesalahan / kegagalan akan melakukan semua pengaturan ulang. Anda mungkin harus memiliki nilai ekstra yang mengatakan mengapa Anda sampai pada keadaan gagal.
Bruce Ediger
FSM Anda harus memiliki setidaknya satu status untuk kesalahan, atau beberapa status kesalahan untuk berbagai jenis kesalahan.
whatsisname
3

Cara terbaik untuk menghindari ini adalah Pengujian Otomatis .

Satu-satunya cara untuk memiliki kepercayaan nyata tentang apa yang kode Anda lakukan berdasarkan input tertentu adalah dengan mengujinya. Anda dapat mengklik di dalam aplikasi Anda dan mencoba melakukan hal-hal yang salah, tetapi itu tidak skala dengan baik untuk memastikan Anda tidak memiliki regresi. Sebagai gantinya, Anda dapat membuat tes yang memasukkan input buruk ke komponen kode Anda dan memastikan bahwa itu menanganinya dengan cara yang waras.

Ini tidak akan dapat membuktikan bahwa mesin keadaan tidak akan pernah bisa rusak, tetapi ia akan memberi tahu Anda bahwa banyak kasus umum ditangani dengan benar dan tidak merusak hal-hal lain.

unholysampler
sumber
2

apa yang Anda cari adalah penanganan pengecualian. Filosofi desain untuk menghindari tetap dalam keadaan tidak konsisten didokumentasikan sebagai the way of the samurai: kembali menang atau tidak kembali. Dengan kata lain: suatu komponen harus memeriksa semua inputnya dan memastikan bahwa ia akan dapat memprosesnya secara normal. Kalau bukan itu masalahnya, ia harus mengeluarkan pengecualian yang berisi informasi berguna.

Setelah pengecualian muncul, itu meluap tumpukan. Anda harus mendefinisikan layer penanganan kesalahan yang akan tahu apa yang harus dilakukan. Jika file pengguna rusak, jelaskan kepada klien Anda bahwa data hilang, dan buat ulang file kosong bersih.

Bagian penting di sini adalah untuk kembali ke kondisi kerja, dan menghindari penyebaran kesalahan. Ketika Anda selesai dengan ini, Anda dapat bekerja pada komponen individu untuk membuatnya lebih kuat.

Saya bukan ahli objektif-c, tetapi halaman ini harus menjadi titik awal yang baik:

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocExceptionHandling.html

Simon Bergot
sumber
1

Lupakan mesin negara-terbatas Anda. Apa yang Anda miliki di sini adalah situasi multi-threading yang serius . Tombol apa saja dapat ditekan kapan saja dan pemicu eksternal Anda bisa mati kapan saja. Tombol-tombolnya mungkin semuanya ada di satu utas, tetapi pemicu bisa mati secara bersamaan pada saat yang sama dengan salah satu tombol atau satu, banyak, atau semua pemicu lainnya.

Yang harus Anda lakukan adalah menentukan keadaan Anda saat Anda memutuskan untuk bertindak. Dapatkan semua tombol dan status pemicu. Simpan di lokal variabel . Nilai asli dapat berubah setiap kali Anda melihatnya. Kemudian bertindak sesuai situasi yang Anda miliki. Ini adalah gambaran bagaimana sistem memandang pada satu titik. Satu milidetik kemudian itu bisa terlihat sangat berbeda, tetapi dengan multi-threading tidak ada arus "sekarang" yang dapat Anda pegang, hanya gambar yang telah Anda simpan dalam variabel lokal.

Maka Anda harus menanggapi keadaan - historis - Anda yang disimpan. Semuanya sudah diperbaiki dan Anda harus memiliki tindakan untuk semua kemungkinan keadaan. Itu tidak akan memperhitungkan perubahan akun yang dibuat antara waktu Anda mengambil foto dan waktu Anda menampilkan hasil Anda, tetapi itulah kehidupan di dunia multi-threading. Dan Anda mungkin perlu menggunakan sinkronisasi agar foto Anda tidak terlalu kabur. (Anda tidak bisa up-to-date, tetapi Anda bisa mendekati mendapatkan seluruh negara Anda dari satu instan tertentu dalam waktu.)

Baca di multi-threading. Anda harus banyak belajar. Dan karena pemicu tersebut, saya tidak berpikir Anda dapat menggunakan banyak trik yang sering disediakan untuk membuat pemrosesan paralel menjadi mudah ("Worker Threads" dan semacamnya). Anda tidak melakukan "pemrosesan paralel"; Anda tidak mencoba menggunakan 75% dari 8 core. Anda menggunakan 1% dari keseluruhan CPU, tetapi Anda memiliki utas yang sangat independen dan sangat berinteraksi, dan perlu banyak pemikiran untuk menyinkronkannya dan menjaga sinkronisasi agar tidak mengunci sistem.

Uji pada mesin single core dan multi-core; Saya menemukan mereka berperilaku agak berbeda dengan multi-threading. Mesin-mesin single-core menghasilkan lebih sedikit bug multi-threading, tetapi bug-bug itu jauh lebih aneh. (Meskipun mesin multi-core akan merusakkan pikiran Anda sampai Anda terbiasa dengannya.)

Satu pemikiran terakhir yang tidak menyenangkan: ini bukan hal yang mudah untuk diuji. Anda harus membuat pemicu acak dan menekan tombol dan membiarkan sistem habis untuk sementara waktu untuk melihat apa yang muncul. Kode multi-utas tidak deterministik. Sesuatu dapat gagal sekali dalam satu miliar berjalan, hanya karena waktunya mati untuk nanodetik. Masukkan pernyataan debug (dengan pernyataan if-hati-hati untuk menghindari 999.999.999 pesan yang tidak dibutuhkan) dan Anda perlu membuat satu miliar berjalan hanya untuk mendapatkan satu pesan yang bermanfaat. Untungnya, mesin sangat cepat akhir-akhir ini.

Maaf untuk membuang semua ini pada Anda ini di awal karir Anda. Mudah-mudahan seseorang akan datang dengan jawaban lain dengan cara mengatasi semua ini (saya pikir ada hal-hal di luar sana yang mungkin menjinakkan pemicunya, tetapi Anda masih punya pemicu / konflik tombol). Jika demikian, jawaban ini setidaknya akan memberi tahu Anda apa yang Anda lewatkan. Semoga berhasil.

RalphChapin
sumber