Kiat tentang cara menyebarkan praktik Berorientasi Objek [ditutup]


14

Saya bekerja untuk perusahaan menengah yang memiliki sekitar 250 pengembang. Sayangnya, banyak dari mereka yang terjebak dalam cara berpikir prosedural dan beberapa tim terus memberikan aplikasi Script Transaksional besar , padahal sebenarnya aplikasi tersebut mengandung logika yang kaya. Mereka juga gagal mengelola dependensi desain, dan berakhir dengan layanan yang bergantung pada sejumlah besar layanan lain (contoh bersih dari Big Ball of Mud ).

Pertanyaan saya adalah: Bisakah Anda menyarankan bagaimana menyebarkan jenis pengetahuan ini?

Saya tahu bahwa permukaan masalahnya adalah aplikasi ini memiliki arsitektur dan desain yang buruk. Masalah lain adalah bahwa ada beberapa pengembang yang menentang penulisan segala jenis tes.

Beberapa hal yang saya lakukan untuk mengubah ini (tapi saya gagal atau perubahannya terlalu kecil)

  • Menjalankan presentasi tentang prinsip-prinsip desain (SOLID, kode bersih, dll).
  • Lokakarya tentang TDD dan BDD.
  • Tim pelatihan (ini termasuk menggunakan sonar, findbugs, jdepend, dan alat lainnya).
  • Pembicaraan IDE & Refactoring.

Beberapa hal yang saya pikirkan untuk dilakukan di masa depan (tapi saya khawatir hal itu mungkin tidak baik)

  • Bentuk tim penginjil OO, yang menyebarkan cara berpikir OO dalam tim yang berbeda (orang-orang ini perlu mengubah tim setiap beberapa bulan).
  • Menjalankan sesi tinjauan desain, untuk mengkritik desain dan menyarankan perbaikan (bahkan jika perbaikan tidak dilakukan karena keterbatasan waktu, saya pikir ini mungkin berguna)

.

Sesuatu yang saya temukan dengan tim yang saya latih, adalah bahwa begitu saya meninggalkan mereka, mereka kembali ke latihan lama. Saya tahu saya tidak menghabiskan banyak waktu dengan mereka, biasanya hanya satu bulan. Jadi apa pun yang saya lakukan, itu tidak menempel.

Saya minta maaf pertanyaan ini dipenuhi dengan frustrasi, tetapi alternatif untuk menulis ini adalah memukul kepala saya sampai saya pingsan.



ElYusubov, "standar" adalah melakukan TDD, yang lagi-lagi tidak semua tim mengikuti. Dan beberapa tim bahkan melakukan BDD dengan hasil yang cukup bagus. (TDD dan BDD adalah Luar-dalam, seperti pemrograman modular).
Augusto

10
Tolong, jangan melihat OO sebagai sesuatu yang dikirim surga yang akan atau harus menyelesaikan masalah Anda. Tentu saja itu terlalu picik. OO mungkin memiliki manfaat tetapi di sini ada beberapa pandangan berbeda tentang subjek: existentialtype.wordpress.com/2011/03/15/… Cobalah untuk tidak fokus pada OO atau bahkan paradigma itu sendiri tetapi mencari praktik terbaik, yang bekerja untuk Anda, cs. brown.edu/~sk/Publications/Papers/Published/…
AndreasScheinert

Andreas, saya ingin orang belajar FP dan menerapkan prinsip-prinsip dalam OO !!! Saya setuju dengan Anda 100%. Masalah yang saya miliki adalah bahwa beberapa pengembang merasa nyaman melakukan hal-hal dengan cara yang sama seperti yang telah mereka lakukan sejak mereka mulai bekerja, dan dalam perjalanan mereka belum meningkatkan keterampilan solusi mereka.
Augusto

3
Jangan mencoba "Sebarkan Firman". Kemakmuran malapetaka dan kehancuran yang dikhotbahkan dari tumpuan tidak turun juga dengan Lulusan Universitas Abad 21 seperti yang mereka lakukan dengan Petani Abad 15.
mattnz

Jawaban:


19

Jangan mencoba menekan OOP, itu hanya akan memperburuk keadaan. Bukan karena OOP adalah ide yang buruk secara umum: bukan. Tetapi karena tampaknya siapa pun yang bertanggung jawab atas kode bola rambut itu tidak hanya kekurangan alat untuk menghindari masalah ini, tetapi juga pengalaman dan, yang lebih penting, motivasi.

Orang yang memiliki keinginan untuk menulis kode bersih akan melakukannya dalam paradigma apa pun, baik itu OOP, prosedural, fungsional, dll. Tetapi tidak semua programmer seperti ini, dan jika Anda mendorong alat kode bersih apa pun ke orang yang tidak memahami kebutuhan, Anda akan berakhir dengan alat-alat ini disalahgunakan seperti alat yang sudah ada. Anda akan melihat metode yang tidak terkait dikelompokkan ke dalam kelas, kelas yang diwarisi dari kelas yang tidak terkait, visibilitas metode yang ditetapkan berdasarkan debug-and-error debugging daripada desain sadar, metode statis yang tidak boleh metode statis dan non-statis yang seharusnya, singkatnya , Anda akan membuang-buang waktu.

Sebaliknya, lihat apakah Anda dapat berinvestasi dalam meningkatkan kesadaran untuk pemeliharaan dan keanggunan. Lagipula, tujuan inti dari OOP tidak berbeda dari strategi manajemen kompleksitas lainnya (yang merupakan inti dari paradigma pemrograman): enkapsulasi, modulasi, penggandaan longgar, saling ketergantungan tingkat rendah, menjaga keadaan yang dapat berubah dan ruang lingkupnya untuk minimum, dll. dll. OOP tentu bukan satu-satunya paradigma yang memberi Anda alat yang Anda butuhkan untuk mencapai ini.

Yang membawa saya ke poin terakhir: OOP adalah ide yang bagus, dan itu bekerja dengan baik untuk beberapa jenis masalah, tetapi (dan saya berbicara baik dari pengalaman saya sendiri dan memparafrasekan pendapat beberapa orang hebat di sini) untuk berbagai jenis masalah, itu benar-benar tidak cocok. Ketika Anda baru masuk ke OOP, dan kode spageti semi-prosedural adalah satu-satunya alternatif yang Anda kenal, OOP secara alami muncul sebagai hadiah dari surga (dan secara relatif, itu), dan Anda cenderung mendekati semua masalah sebagai paku untuk palu OOP Anda. Itu wajar, dan mendorong OOP ke (dan melampaui) keterbatasannya adalah cara yang baik untuk membangun keterampilan OOP Anda, jadi itu tidak semuanya negatif. Tapi mungkin (mungkin saja) basis kode khusus ini tidak perlu OOP. Mungkin itu akan mendapat manfaat lebih banyak dari arsitektur prosedural,

TL; DR: Jika Anda ingin menginjili apa pun, biarkan itu (platform-agnostik) praktik pengkodean yang baik, bukan paradigma atau metodologi tertentu.


4
+1: Untuk mengenali bahwa OOP tidak akan menyelamatkan mereka. Para penginjil sering lupa bahwa .....
mattnz

1
+1: Tapi saya akan mendapat suara positif 10 kali jika saya bisa. Meskipun benar bahwa OOP menawarkan dukungan yang lebih baik untuk menyusun kode daripada pemrograman prosedural, OOP saja tidak cukup. Sama dengan SCRUM, TDD, dan yang lainnya. Saya pikir ini semua adalah alat yang berguna tetapi mereka tidak dapat menggantikan (1) sikap dasar setiap programmer untuk menulis kode modular yang sederhana, bersih, (2) karya satu atau lebih arsitek yang diakui seperti itu oleh seluruh tim dan bahwa memastikan bahwa arsitektur kode keseluruhan tetap koheren. Tanpa prasyarat ini, sebuah tim dapat dengan mudah menghasilkan bola lumpur berorientasi objek yang besar.
Giorgio

5

Anda tidak dapat membuat siapa pun berubah yang belum ingin berubah. Itulah sebabnya tim yang Anda latih telah kembali ke cara lama mereka.

Jadi, pertanyaan Anda seharusnya adalah "bagaimana cara membuat pengembang ingin berubah ke pendekatan OO?"

Mulai dari yang sederhana, mulai dari yang kecil, biarkan hal-hal membangun dari sana. Tunjukkan manfaat kepada pengembang individu, bukan manfaat abstrak atau filosofis untuk kode, pengembang lain, atau perusahaan.

Tunjukkan bagaimana berbagai teknik OO akan menghasilkan lebih sedikit kode yang harus mereka tulis serta waktu pengembangan yang lebih cepat. Hampir semua pengembang akan mendengarkan proposal yang akan membuat pekerjaan mereka lebih mudah.

Kemudian mulailah menunjukkan bagaimana teknik OO akan menghasilkan kode yang lebih mudah dipelihara. Setiap orang di lingkungan semacam itu hidup dalam ketakutan membuat " perubahan " yang melenyapkan sepertiga dari aplikasi produksi. Enkapsulasi adalah kunci untuk menghindari risiko ini dan memungkinkan setiap lapisan aplikasi untuk mempertahankan kontraknya dengan lapisan lainnya.

Saya akan melihat bagaimana data sedang dikirimkan. Jika daftar panjang variabel setiap waktu, pertimbangkan membungkus beberapa dari mereka dalam struktur (atau terkesiap! Kelas !!!) sebagai langkah awal. Cukup membungkus data dalam suatu objek adalah awal dari kontrak antar lapisan.

Pada tingkat yang lebih luas - pertimbangkan untuk menerima dukungan manajemen untuk upaya ini jika Anda belum melakukannya. Manajemen perlu melihat manfaat nyata dari penurunan cacat dan risiko yang lebih rendah dari melakukan perubahan. Pada akhirnya, proses refactoring harus mengarah pada waktu pengembangan yang lebih cepat, tetapi itu adalah manfaat jangka panjang.

Gagasan Anda tentang tim peninjau dan penginjil OO adalah yang baik. Perlu lebih dari sekadar Anda yang mendorong agenda ini.


Terima kasih atas jawaban Anda pada Glen! Saya merasa bahwa saya melakukan apa yang Anda sarankan. Ada cukup banyak dukungan manajemen dan beberapa pimpinan tim lelah karena diperlambat oleh tim yang tidak mengikuti praktik yang baik, dan akibatnya itu membuat pekerjaan mereka lebih sulit. Apa yang Anda katakan pada kalimat pertama Anda sangat benar dan itu bagian dari masalahnya. Saya pikir beberapa orang terlalu terbiasa melakukan hal yang salah dan tidak memiliki motivasi untuk meningkat.
Augusto

4

Pengalaman saya adalah beralih dari pola pikir prosedural ke pola pikir OO adalah rintangan besar. Ini membutuhkan ketekunan yang gagal bertahan banyak pengembang. Ini terutama karena dasar-dasar OO dipandang sebelah.

Bentuk tim penginjil OO, yang menyebarkan cara berpikir OO dalam tim yang berbeda (orang-orang ini perlu mengubah tim setiap beberapa bulan).

adalah ide yang bagus. Ini harus menyeluruh dan OO harus dibicarakan dari bawah ke atas. Ketika saya belajar OO anekdot sejarah banyak membantu.

Saya juga menyarankan,

  • Karena motivasi adalah kuncinya, memotivasi mereka merinci bagaimana OO dapat meningkatkan pekerjaan mereka, terutama pemeliharaan kode.
  • Lakukan peninjauan kode dan tunjukkan cara refactor menerapkan komposisi, pewarisan, polimorfisme, dan pola.
  • Perkenalkan proses yang baik seperti SCRUM dan libatkan pengembang di dalamnya.
  • Buat buku bacaan seperti 'Refactoring' dan 'Refactoring to Patterns' wajib.

Terima kasih atas jawaban Anda, Shuvo. Kami sudah melakukan tinjauan SCRUM dan kode (tapi seringkali reviewer adalah salah satu orang yang tidak tahu prinsip OO) ... Dan saya gagal pada hal pertama yang Anda sarankan. Saya mencoba memotivasi tim, tetapi dengan sedikit keberhasilan :(. Tentang membuat wajib untuk membaca beberapa buku. Saya tidak pernah melihatnya bekerja, karena orang mengambil salinan dan tidak pernah membacanya, mencegah orang lain membacanya.
Augusto

1

Saya setuju dengan Shuvo Naser. Ini adalah rintangan besar, jadi perlakukan itu lebih seperti pendakian. Mempelajari cara mendesain seluruh aplikasi menggunakan OOP akan membutuhkan waktu.

  1. Identifikasi mereka yang memahami OOP dan gerakkan mereka lebih dekat ke pemimpin tim, pelatih, perancang, peninjau kode, dll.
  2. Gunakan proyek yang ada sebagai referensi pelatihan. Mungkin mereka yang berada di # 1 ada di tim itu.
  3. Refactor beberapa proyek yang ada. Ini dapat membantu beberapa orang membangun jembatan antara kode prosedural mereka ke kode OO. Mulailah dengan dasar-dasar. Mereka harus melihat kapan, di mana, dan mengapa Anda menggunakan prinsip-prinsip ini.
  4. Libatkan mereka dalam sesi desain dengan orang-orang yang tahu apa yang mereka lakukan.
  5. Letakkan mereka di tim pengembang dengan seseorang yang dapat memberikan panduan desain dan pastikan proyek mematuhi prinsip-prinsip OO (Dengan asumsi alasan Anda ingin melakukan ini sejak awal adalah karena hal itu akan meningkatkan pengembangan.).

Adopsi jarang mendahului melihat manfaat. Kita berbicara tentang desain yang rumit dan tidak menggunakan Lembar Sampul Laporan TPS .


-1. Jawaban ini hampir seolah-olah untuk manajer, bukan untuk pengembang normal. Dia tidak bisa "menggerakkan" orang dan dia tidak bisa "melibatkan" orang. IMO.
Euforia

+1. Ini adalah masalah manajemen, dan harus ditangani sebagai satu. Manajemen menengah dan bawah (pemimpin tim adalah manajemen) yang menentukan gaya. Perubahan dalam perusahaan datang dari bawah hanya jika transparan bagi manajemen. Beralih ke OOP membutuhkan perubahan dalam berpikir di atas. Menjaga proses pengembangan prosedural / air terjun agak laknat untuk OOP.
David Hammen

@Euphoric - Anda hanya perlu persetujuan manajemen. OP menyebutkan "tim yang saya latih". Mungkin dia bukan manajemen tetapi memiliki pengaruh pada cara kerjanya.
JeffO

@ Jeff Ya, Anda benar. Tetapi semuanya akan turun jika manajemen ingin mendukung upaya-upaya tersebut. Pada pekerjaan terakhir saya, tidak mungkin melakukan sesuatu seperti itu, karena manajemen tidak tertarik dengan pendidikan pengembang.
Euforia

Terima kasih atas komentar kalian. Saya bukan manajer, hanya arsitek yang frustrasi. Saya memiliki pengaruh dengan para manajer, khususnya jika itu berarti: lebih cepat, lebih murah dan lebih baik. Sayangnya, tidak ada cukup arsitek di perusahaan untuk membantu pada setiap proyek, dan sebagian besar proyek di mana kualitasnya tidak cukup baik, tidak memiliki arsitek yang berdedikasi.
Augusto

1

Anda Sudah Punya Ide Bagus

Gagasan yang Anda uraikan dalam pertanyaan Anda terdengar sangat bagus. Merupakan kejutan besar bahwa Anda tidak menemukan kesuksesan. Ini adalah 2012 dan revolusi berorientasi objek telah lama berlalu dari negara-of-the-art ke negara-of-the-praktek. Sepertinya kecuali jika Anda memiliki turn over yang sangat rendah dan perekrutan yang sangat sedikit, Anda akan mengalami kesulitan untuk tidak mendapatkan beberapa lusin atau bahkan ratusan programmer berorientasi objek yang baik.

Agile atau Berorientasi Objek?

Anda menyebutkan beberapa teknologi Agile seperti TDD dan beberapa konsep baru, jadi jangan terlalu keras pada orang-orang karena tidak merangkul sesuatu yang masih diperjuangkan secara aktif oleh beberapa tim manajemen. Beberapa mengklaim untuk memeluk Agile, tetapi ketika mereka membicarakannya, itu berarti apa yang mereka katakan artinya. Organisasi tidak dicirikan oleh tim yang membuat keputusan dan beradaptasi, melainkan oleh kontrol gaya kontrak yang hierarkis.

Tetapi kembali ke berorientasi objek. Anda tidak menyebutkan analisis atau desain berorientasi objek, dan saya tidak yakin bahasa pemrograman mana yang memberi jalan kepada bahasa pemrograman berorientasi objek. Saya tahu UML mengalami masalah popularitas di antara banyak programmer berorientasi objek. Setelah dilatih sepenuhnya dalam OOAD, saya percaya itu mungkin seperti mempelajari budaya dan sejarah negara yang bahasa alami yang ingin Anda pelajari. Sebagai contoh, jika saya ingin belajar bahasa Yunani, saya bisa belajar alfabet, kosa kata, dan tata bahasa, tetapi jika saya mengabaikan sejarah dan budaya yang kaya, saya akan kehilangan banyak hal. Bagaimanapun, jika Anda mempelajari semua tentang bahasa pemrograman berorientasi objek, tetapi tidak ada tentang OOAD, saya pikir kesempatan penting telah hilang.

Masalah untuk Diatasi?

Jembatan terlalu jauh? Jika Anda meminta orang untuk mempelajari satu hal kecil dalam seminggu, dalam setahun, di antara orang-orang yang berpartisipasi, akan ada banyak perubahan. Jika Anda meminta mereka untuk mengubah semua yang mereka tahu, itu akan disambut oleh beberapa orang, sulit bagi banyak orang, dan tidak mungkin bagi orang lain. Beberapa perubahan seperti kontrol sumber dilokalkan. Anda transisi dari tidak melakukannya sebelumnya, Anda memiliki pelatihan yang tidak menekankan batas memori, seseorang memandu Anda melalui itu pertama kali, dan kemudian sehari-hari cukup mudah.

Perubahan lainnya meresap. Misalnya, membuang C dan beralih ke Java membutuhkan pelatihan, pengaturan, dan perubahan besar dalam sehari-hari untuk mengadopsi IDE baru, kompiler baru, bahasa baru, API baru, model penyebaran baru, dll. Ini adalah jenis hal yang paling sering terjadi bersamaan dengan program percontohan atau restrukturisasi perusahaan.

Memimpin Revolusi? Jika orang-orang yang melakukan pekerjaan ini memiliki sejarah penghargaan, dan perusahaan tidak tampak dalam bahaya gagal, apa motivasi mereka untuk berubah? Jika Anda tampak seperti orang luar yang ingin menunjukkan arah dan membiarkan mereka bertanggung jawab atas hasil yang tidak dapat mereka prediksi, itu mungkin tampak seperti semua risiko, tidak ada imbalan.

Posisi Kekuatan atau Kepemimpinan Ide? Banyak organisasi beroperasi berdasarkan kekuatan posisi. Jika Anda kurang mendapat dukungan nyata dari manajer, kepala seksi, direktur, dan Wakil Presiden, Anda hanyalah pemimpin gagasan. Beberapa orang berada dalam posisi berbahaya karena memiliki satu ide, dan tidak bisa mendapatkan ide kedua. Jika Anda bisa menunjukkan kepada mereka alih-alih memberi tahu mereka, itu akan membantu menenangkan skeptis dan menarik sekutu yang berbakat.

Basis Dukungan Terlalu Kecil? Lakukan triase di antara 250 orang itu dan mengelompokkannya ke dalam tiga kategori: siap merangkul, mau belajar, dan tidak mau belajar. Anda memiliki alasan yang bagus untuk frustrasi dengan beberapa orang yang tidak tertarik melakukan perubahan. Anda mungkin juga mendorong tali. Ini usaha yang sia-sia. Jika Anda memiliki perasaan terhadap siapa yang mendukung perubahan, Anda dapat mengetahui minat mereka.

Tidak seperti triase medis di mana pilihan etis dan praktis adalah untuk membantu kelompok menengah yang dapat membuatnya dengan bantuan, Anda dapat menginvestasikan energi dan waktu Anda berdasarkan penilaian dan preferensi Anda. Untuk kesuksesan Anda, mengapa tidak memupuk kelompok yang siap merangkul ide-ide baru? Mereka mungkin sedikit yang pertama, tetapi seperti bola salju, visibilitas dan kredibilitas Anda sebagai advokat akan tumbuh. Segera orang akan bertanya kepada Anda kapan pelatihan berikutnya.

Di dalamnya untuk Jangka Panjang? Sampai Anda memupuk seorang juara untuk membawa barang setelah Anda, Anda harus berharap untuk menginvestasikan waktu untuk membangun hubungan. Anda mungkin perlu tinggal bersama tim yang Anda latih selama lebih dari satu bulan. Sampai tim memiliki praktik yang ditingkatkan untuk diri mereka sendiri, Anda hanyalah polisi teknologi atau metodologi. Mentoring adalah proses yang bisa memakan waktu bertahun-tahun. Ada banyak hal yang pengembang Anda tidak ingin lakukan yang menurut Anda penting (Anda secara khusus menyebutkan pengujian unit, saya pikir). Mungkin perlu beberapa saat untuk membangun visi bersama tentang nilai yang dihasilkannya. Saya mengetahui hal ini dari pengalaman karena saya pernah menganjurkan untuk alat kode cakupan di perusahaan Fortune 500 yang memiliki reputasi yang hebat untuk kualitas, tetapi manajer dan rekan kerja sama-sama khawatir tentang berkomitmen untuk itu.

Pakar atau Akar Rumput? Jauh lebih cepat daripada mentoring untuk menumbuhkan dukungan akar rumput yang berasal dari masing-masing anggota tim. Dimulai dengan tim yang terdiri dari sepuluh spesialis perangkat lunak, jika saya memiliki pilihan untuk meminta satu orang mengerjakan proses sepanjang waktu atau sepuluh orang mengerjakan proses sepuluh persen dari waktu, saya akan memilih yang kedua. Proses akar rumput memungkinkan para advokat untuk merasakan dampak dari pendekatan tersebut, dan agar pendekatan tersebut dirancang untuk memecahkan masalah tim yang memiliki pekerjaan.

Apakah Anda melihat Freedom Line? Bagian dari memperkenalkan "Praktik Terbaik" adalah membuat orang melepaskan kebebasan untuk melakukan sesuatu dengan cara yang sama. Melepaskan kebijaksanaan programmer akan lebih enak jika Anda mencari peluang untuk meninggalkan banyak pilihan kepada pengembang. Apa yang mereka pilih digambarkan dari apa yang diamanatkan oleh partisi yang dapat kita sebut garis kebebasan. Mungkin diperlukan untuk divisi yang serupa dan dibenarkan tentang praktik organisasi, regional / situs, tim, dan pribadi.


0

Ini seharusnya menjadi komentar, tetapi karena saya tampaknya belum dapat mengomentari hal-hal, mungkin juga menjadi jawaban.

Hal yang paling penting dalam terobosan semacam ini (baik itu OOP atau perubahan paradigma lainnya, katakanlah, pemrograman fungsional atau apa pun yang muncul di tahun berikutnya) adalah MELAKUKAN TINJAUAN KODE DAN PEMROGRAMAN PEER . Menemani mereka, berjalan tim ke cara berbeda dalam melakukan hal-hal yang akan membantu mereka.

Jalur pribadi saya ke pemrograman berorientasi objek dimulai ketika beberapa asshat acak yang melakukan review kode menghukum saya karena melakukan hal-hal dengan cara modular dan mempertahankan status tanpa menjadi C + OO penuh; pikirkan kode seperti

extern float clients_total;

void client_add(float sum);  
void client_substract(float sum);
float client_get_total();

(perhatikan bahwa clients_total mungkin sepenuhnya berlebihan, menjadi contoh yang sangat tidak direncanakan)

Dan saya akhirnya melakukan ini hanya ketika rekan kerja yang lebih senior hanya menunjuk layar saya dan berkata "lihat, jika Anda menulis hal yang sama lebih dari satu kali, gunakan prosedur atau fungsi dan sebut saja berulang kali".

Pembicaraan dan pertemuan serta praktik opsional tidak akan membuat mereka melakukan perubahan paradigma atau memperkenalkan praktik baru, karena tidak ada dorongan nyata untuk melakukannya selain rasa ingin tahu yang murni. Di sisi lain, membuat tidak melakukan hal yang buruk atau hanya disukai pada hal meningkatkan tingkat adopsi dengan sangat baik.

Bersiaplah untuk pengembangan rengekan dan berorientasi kelas yang akan terjadi sampai mereka memasukkan desain yang tepat ke dalam apa yang mereka lakukan. Anda akan melihat banyak hal yang akan membuat Anda sedikit mati di dalam, tetapi seperti itulah jalan menuju pembelajaran.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.