Memperkenalkan pemrograman fungsional ke dalam lingkungan pengembangan Anda [ditutup]


15

Ini adalah cerita yang panjang tetapi saya akan mencoba untuk meringkasnya sebaik mungkin. Kami adalah .NET shop yang menulis perangkat lunak untuk berbagai jenis dana yang berbeda. Sebagai contoh, kami menulis perangkat lunak manajemen klaim kesehatan, perangkat lunak manajemen pensiun, perangkat lunak 401 (k) dan beberapa hal jenis keuangan lainnya.

Sekarang kita memasuki bidang baru: turunan dan jenis pekerjaan analisis kuantitatif, yang tampaknya sangat menarik. Ini adalah sesuatu yang akan turun dalam 8-12 bulan ke depan, saya sudah diberitahu.

Sekarang, saya telah belajar beberapa pemrograman fungsional saya sendiri, terutama hanya pandangan sekilas pada berbagai bahasa melalui buku ini, tetapi tidak pernah benar-benar menggali jauh ke dalamnya. Sekarang, karena kami adalah toko NET. Saya pikir F ​​# mungkin pilihan yang baik, karena kami berpotensi memanfaatkan beberapa perpustakaan .NET dan pengetahuan yang ada.

Pertanyaan saya adalah, dari mana harus memulai? Saya mengalami waktu yang sangat sulit untuk mencari tahu apakah saya harus pergi dengan Haskell, Erlang, Scala, F #, dll. Mereka semua tampak sangat menarik dan mampu dan terus terang ini mungkin kesempatan yang baik untuk keluar karena ketergantungan pada Microsoft.

Adakah yang mengalami situasi serupa? Jika demikian, apa pengalaman Anda yang membuat fungsional dan apa yang Anda pilih dan mengapa? Saya tahu ini adalah pertanyaan besar, tetapi saya tidak tahu ada pengembang yang menggunakan metode fungsional saat ini, jadi saya tidak punya tempat lain selain menyalakan Google tanpa henti dan menemukan perang api di mana-mana dengan bahasa fungsional terbaik.


direkomendasikan membaca: Di mana untuk memulai
nyamuk

Jawaban:


14

Prototipe, prototipe, prototipe! Ambil sedikit fungsi bisnis yang menurut Anda memerlukan pemrograman fungsional dan coba berbagai bahasa dan lihat apakah mereka benar-benar memberi Anda manfaat dan interoperabilitas yang Anda cari.


Saran yang bagus dan saya akan mengindahkannya, sebenarnya saya sedang melakukan instalasi Erlang sekarang untuk mencobanya.
Nodey The Node Guy

10

Pertanyaan pertama yang harus Anda jawab dengan jujur ​​adalah mengapa Anda mempertimbangkan untuk menggunakan bahasa fungsional. Jika Anda tidak dapat membenarkan alasan bisnis untuk peralihan tersebut, maka Anda tidak boleh melakukannya. Dengan kata lain, ingin memperkenalkan kerangka kerja baru, bahasa atau teknologi baru lainnya ke dalam lingkungan kerja Anda hanya karena Anda ingin mempelajarinya atau karena sepertinya hal "keren" berikutnya jelas merupakan kesalahan. Jadi, pertama-tama Anda perlu bertanya pada diri sendiri apa motivasinya.

Jika Anda benar-benar merasa Anda perlu bahasa fungsional untuk menyelesaikan masalah tertentu, dan dengan asumsi sebagian besar bahasa fungsional utama akan memenuhi persyaratan Anda, maka saya akan menggunakan yang paling matang dan yang dengan komunitas pengguna terbesar. Erlang adalah pilihan yang baik dan memenuhi kedua persyaratan ini, namun, dalam lingkungan murni ms / .NET, saya dapat memahami menggunakan F #.


2
@ennukiller - Saya pasti bisa melihat bahwa pemrograman fungsional akan menjadi pilihan yang baik bagi kami dan saya tidak akan berbohong - Saya juga suka menggunakannya hanya untuk stimulasi intelektual semata yang akan diberikannya. Kami akan melakukan perhitungan dalam jumlah besar dan saya ingin memanfaatkan multi-core. Juga, sangat penting bahwa setiap fungsi matematika dibuktikan benar, saya mengerti bahwa mungkin lebih mudah dengan fungsional.
Nodey The Node Guy

2
Jika Anda membutuhkan bukti, pemrograman fungsional murni adalah yang terbaik. Beberapa saran di sini adalah untuk add-on fungsional untuk bahasa imperatif - mereka mungkin lebih akrab, tetapi tidak akan memberi Anda kode yang terbukti benar. Di hadapan efek samping, Anda tidak dapat menggunakan fakta bahwa x = x ('transparansi referensial'), dan Anda harus membuktikan bahwa x nanti dalam kode masih memiliki nilai yang sama seperti sebelumnya. Dalam beberapa bahasa, misalnya, dapat terjadi bahwa x:=3; y:=10; x:=add(x,x);hasil dalam xyang bukan 6 dan yyang bukan 10. Untuk membuktikan fungsi Anda benar dalam konteks ini tidak praktis.
AndrewC

9

Saya sangat setuju dengan F # untuk toko dengan basis kode .Net yang ada, sama seperti saya sangat setuju dengan Scala untuk toko dengan basis kode Java yang ada.

Pemrograman fungsional adalah alat seperti yang lain. Digunakan dengan baik, dan terintegrasi dengan bagaimana Anda sudah mengembangkan kode, itu dapat membuat Anda lebih produktif dengan membuatnya lebih mudah untuk alasan tentang apa yang dilakukan kode Anda. Mengganti bahasa masih jauh dari gratis, jadi taruhan terbaik Anda adalah solusi yang memungkinkan Anda menggunakan sebanyak mungkin kode Anda selama mungkin selama masa transisi. Cara paling pasti untuk gagal memperkenalkan bahasa baru ke lingkungan Anda, bagaimanapun, adalah memberi tahu rekan kerja Anda bahwa mereka harus menulis ulang semua yang mereka punya sejauh ini untuk melihat manfaat dari perubahan itu, pada titik ini, Anda masih mencoba menjualnya.


7

Saya akan merekomendasikan memulai pemrograman fungsional tanpa juga belajar bahasa baru segera. Itu hanya membuatnya lebih sulit jika Anda mencoba mempelajari paradigma baru ketika Anda juga mencoba memahami sintaksis bahasa baru.

Tentu saja, bahasa yang telah secara khusus dikembangkan untuk melakukan pemrograman fungsional akan memiliki beberapa keuntungan (seperti memiliki konstruksi spesifik seperti pemahaman dan membuat struktur data tidak dapat diubah secara default), tetapi secara umum langkah terbesar yang harus dilakukan adalah mengubah pemikiran Anda menjadi fungsional. gaya. C # sangat bagus untuk melakukan itu.

Pada dasarnya, Anda hanya berhenti mengubah status kode Anda. Saya telah melakukan ini menggunakan Java dan bahkan lebih mudah dengan C # karena Anda memiliki lambdas. Setelah Anda memahami gaya itu dan merasakan apa yang baik untuknya, akan sangat mudah untuk mengambil bahasa fungsional (terlepas dari apakah itu F # yang Anda pilih atau Erlang) dan menjadi sangat produktif dengannya.


1
+1: Saya setuju dengan Anda. Saya juga sudah mulai membuat kode dengan gaya yang lebih fungsional di Java dan C ++ (menggunakan variabel yang lebih final dan const, memecah operasi kompleks menggunakan komposisi fungsi, dan sebagainya). Saya pikir ini pasti meningkatkan gaya pemrograman saya di Java dan C ++. Setelah beberapa saat, ketika seseorang merasa siap untuk melangkah lebih jauh, seseorang dapat mencoba bahasa fungsional (Haskell, Ocaml, SML, Lisp, Scala, F #, dll.)
Giorgio

1

Jika yang Anda inginkan adalah mempelajari dan memahami pemrograman fungsional, maka cukup instal IronPython dan fokus pada fitur fungsional di Python. Paling buruk, Anda akan mempelajari alat yang dapat diintegrasikan dengan C # untuk mengurangi jumlah baris kode dalam aplikasi dan membantu Anda memberikan lebih banyak produk bebas bug lebih cepat dari jadwal.

Lihat presentasi DaBeaz tentang generator untuk contoh bagaimana pendekatan fungsional dalam Python dapat menyederhanakan hal-hal kompleks http://www.dabeaz.com/generators/

Selain itu, saya pikir Anda sebaiknya menginvestasikan waktu bersama Scala. Ini berjalan pada. NET dalam mode beta, sehingga Anda dapat menginstal dan menggunakannya hari ini untuk tujuan pembelajaran, dan pada musim gugur, itu akan berada dalam mode rilis untuk .NET. Ini berarti bahwa Anda dapat menulis kode dalam Scala yang portabel di JVM dan .NET. Dan, karena Scala berbasis di sekitar Aktor dan penyampaian pesan, sangat, sangat mudah untuk membangun aplikasi yang terbuat dari beberapa program terpisah yang berjalan pada beberapa mesin yang terpisah. Ketika Anda menambahkan portabilitas .NET / JVM ke dalam campuran, maka ada aspek lain yang perlu dipertimbangkan. Anda bisa memiliki satu aplikasi yang memanfaatkan perpustakaan Java pihak ketiga dan pihak ketiga. Perpustakaan NET tanpa main-main dengan mengembangkan protokol untuk membuat mereka berkomunikasi. Kedua proses akan ditulis dalam Scala, dan akan menggunakan pesan jarak jauh Scala (aktor jarak jauh) untuk berkomunikasi. Lihatlah Akka, perpustakaan yang sepertinya akan menjadi bagian dari perpustakaan standar Scala berdasarkan apa yang dilakukan oleh Typesafe.com.


+1: Untuk menyebutkan Scala dan ketersediaannya pada platform yang berbeda. Pertanyaan: apakah akka akan menggantikan implementasi aktor saat ini di Scala? Atau akankah keduanya ada berdampingan?
Giorgio

Tidak yakin apakah Akka akan menggantikan aktor Scala saat ini dalam waktu dekat, tetapi pencipta Scala Martin Odersky telah bergabung dengan pencipta Akka Jonas Boner di perusahaan Typesafe. Mereka sangat mempromosikan Scala dengan Akka dan sekarang dengan kerangka bermain. Jadi ada kemungkinan bahwa fokus pengembangan akan berada di Akka. Jika Anda hanya belajar aktor dengan Scala, akan lebih baik untuk fokus pada Akka terlebih dahulu.
Michael Dillon

Terima kasih banyak atas informasinya! Saya melihat aktor di Scala tetapi hanya yang sangat dangkal sampai sekarang.
Giorgio

-1

Saya tentu setuju dengan dorongan utama dari jawaban yang diterima, dan mengingat bahwa Anda pada dasarnya menyelam ke hal-hal yang dituju dengan memberi Erlang mencoba sepertinya Anda mungkin memiliki pemahaman yang cukup baik tentang bagaimana Anda belajar dan hanya perlu sedikit dorongan di sebelah kanan arah, begitu jelas itu adalah jawaban yang baik untuk Anda ... Tapi, saya pikir saya akan mendekati pertanyaan itu sedikit berbeda, karena saya melihat bahwa jawaban ini tidak akan banyak membantu saya sama sekali; Saya selalu kode untuk belajar! Jadi, inilah pikiran saya ...

(BTW, saya cenderung melanjutkan dengan detail yang lebih cocok untuk, katakanlah, bab-bab dalam sebuah buku, dan saya yakin saya tidak bisa menahan naluri saya sepenuhnya di sini, tetapi saya akan mencoba cara yang berbeda; saya akan meringkas pikiran saya di sini, dan jika seseorang ingin lebih detail tentang apa pun, atau berpikir sesuatu yang saya katakan menyesatkan dalam format ini, saya akan melakukan yang terbaik untuk mengingat melalui pengingat respons ...)

Untuk mencoba menjaga diri agar tetap pada tugas, inilah pemahaman saya tentang pertanyaan dorong yang diajukan dalam OP; Saya akan menjaga sela-sela seminimal mungkin untuk menjelaskan ....

Pertama, jawaban cepat:

Apakah saya dalam situasi yang sama? Setidaknya mirip; Saya berada di posisi terdepan dalam melakukan berbagai proyek yang terkait ... (CRM / Web / DB / Integrasi Data / dll.)

bagaimana / mengapa saya melakukan lompatan ke fungsional? " Saya melihat beberapa contoh LINQ dan meskipun saya benar-benar memimpikan semacam bahasa query yang terintegrasi dan diketik secara statis [karena saya terutama menggunakan bahasa yang diketik secara statis (terutama C ++, dan kemudian C # )] sepanjang karir saya ... Tapi, itu adalah lingkungan yang cukup cepat saya berada, dan meskipun saya sering berhasil melihat apa yang akan terjadi di masa lalu, saya tidak pernah benar-benar memikirkannya sehingga saya tidak pernah meramalkan bahwa itu akan terjadi. bisa / akan mengizinkan operasi di Plain Old Objects (lol!) dengan mudah; ketika saya melihatnya saya tahu saya harus memilikinya ... jadi, itulah sebabnya dan awal dari caranya: saya fokus pada belajar memahami LINQ .

Empat Pikiran ... errr, tidak itu tidak benar ... Meskipun begitu

Ketika saya membaca jawaban Martijn Verburg , penyebutan fungsi bisnis segera menarik pikiran saya untuk mulai menerapkan kode untuk apa pun yang sedang saya kerjakan ... Bergantung pada seberapa dangkal eksperimen awal itu, saya mungkin menjawab secara berbeda, tetapi dengan asumsi itu hanya mencelupkan jempol kaki Anda ke dalam, saya tidak yakin bahwa saya memiliki sesuatu yang langsung untuk bekerja (atau pekerjaan yang akan segera) yang akan memberi saya kegembiraan / hasrat saya pikir Anda mungkin harus memiliki untuk beberapa masalah pertama yang Anda mulai atasi ...

Saya didasarkan hampir seluruhnya dalam bahasa yang diketik secara statis + metafora dan pola OOP + apa pun yang akhirnya membungkus otak saya secara tidak sengaja sambil memecahkan masalah saya yang sebenarnya selama bertahun-tahun ... Maksudnya adalah, jika Anda memang seperti saya, Anda mungkin memiliki banyak otak yang didedikasikan untuk hal-hal yang tidak akan banyak membantu Anda dengan LINQ / FP.

Saya pikir itu agak seperti pemrograman prosedural vs OO murni: ada banyak hal prosedural yang akhirnya Anda gunakan di OOP, tetapi mereka yang datang ke C ++ dari C tanpa menjadikannya prioritas untuk grok / ken / "dapatkan" OO akhirnya menjadi sangat sangat buruk di C ++. Saya benar-benar telah mewawancarai banyak (15+) lama firmware dan pengembang driver perangkat yang benar-benar berpikir mereka tahu C ++, tetapi yang, paling banyak , memiliki pemahaman yang sangat dasar / buku teks tentang C ++, dengan praktis tidak memiliki pemahaman atau pengalaman dalam OOP — karena mereka tidak pernah benar-benar melakukan OOP ... Mereka menulis kelas serba guna singleton dengan anggota statis dan fungsi statis dengan sejumlah kelas non-statis / non-singleton yang digunakan sebagai struct.

Dan FP memiliki beberapa konsep yang sama (untuk mereka yang tidak mengangkat paradigma) dan hal-hal lain yang sejalan dengan itu, dan (walaupun saya telah menemukan hibridisasi banyak teknik menjadi ideal bagi saya) saya lebih mengerti dan lebih banyak seiring berjalannya waktu betapa terbatasnya pemikiran saya sebelum memasukkan kemampuan fungsional yang nyata ke dalam perangkat saya; Saya telah berhasil mengimplementasikan banyak hal di masa lalu dengan cara yang sedikit lebih kreatif daripada yang mungkin kebanyakan programmer OO, tetapi ketika saya menggunakan konsep bagaimana cara berpikir saya terhambat sebelumnya ... Ada seluruh kelas masalah yang dapat diselesaikan dalam beberapa baris yang digunakan untuk mengambil banyak pekerjaan yang harus dilakukan di C ++ / C #.

tiba-tiba Anda menemukan diri Anda ...

Dalam Posting "Terlalu Panjang"

Anda berada dalam labirin yang berkelok-kelok "tidak membaca", semua sama.

Anda melihat teleconference dalam waktu dekat, dengan cepat mendekat.
> singkat
Uh huh. Tentu. Oke, kita akan mengatakan mode "singkat" adalah "aktif".

Anda melihat teleconference dalam waktu dekat, dengan cepat mendekat.
> apa artinya itu?
Katakan saja. Bukankah kamu harus melakukan sesuatu pagi ini?

Anda melihat teleconference dalam waktu dekat, semakin dekat. 
> hei, apakah itu sebuah petunjuk di belakang Anda?
Apa!? DIMANA?! [Lari menjerit]

> Maaf, saya tidak mengerti APA DI MANA, ulangi?
[Terus berlari dan berteriak, sarkasme tanpa disadari]

Jadi ... Apa yang harus saya pelajari, PSE sayang, PSE sayang?

Saya pribadi mulai di C # dengan LINQ. Itu memungkinkan saya untuk memperkenalkan beberapa konsep sekaligus, dan sementara saya terus-menerus membaca tentang FP dan konsep-konsepnya, dan lebih banyak LINQ, dan hubungan antara keduanya, itu memberi saya jalan ke depan sambil tetap melakukan pekerjaan yang produktif. Saya menambahkan beberapa hal sekaligus, kueri data dengan cepat menjadi alat yang berguna bagi saya tanpa harus mengerti satu ton.

Sekarang, melihat ke belakang, saya agak berharap bisa melakukan proyek berikutnya (ditangani sekitar setahun kemudian) pertama; Saya cukup akrab dengan F # (yang, kebetulan, memberi saya awal yang baik untuk belajar ML (bahasa logam) dan itu adalah turunan lainnya (misalnya, OCaml juga.)

Pada dasarnya, saya pikir jawaban yang layak untuk 'apa' tergantung pada menemukan pasangan yang baik dari beberapa masalah pemrograman yang menarik minat Anda, tetapi tentu saja harus dipasangkan dengan sedikit FP yang ingin Anda pelajari ... (dan Anda dapat bilas / ulangi / busa setelah mengetuk sesuatu dari daftar ...) Dan, tentu saja, Anda selalu berakhir belajar sedikit lebih dari hal utama yang Anda ingin lakukan; pada awalnya saya mengambil beberapa langkah kecil, tetapi kemudian saya akhirnya melakukan hal-hal yang lebih besar dan membiarkan hal-hal kecil jatuh ke tempatnya sementara saya melakukan itu.

Pertama, apa yang mengapungkan kapal Anda? Terutama pada awalnya yang terbaik adalah memiliki sesuatu yang menyenangkan dan menarik (untuk Anda) dan itu akan membuat Anda cukup tertarik untuk menjadikannya bermanfaat bagi Anda. Jadi, masalah TKI untuk dikerjakan, dan teknik yang mengatasi masalah itu ... LINQ dan kueri data inline untuk saya pada awalnya. Rekursi adalah satu lagi untuk saya, termasuk rekursi ekor, saya menggali GodelEscherBach-ness-nya; dan saya telah membaca tentang rekursi ekor. Sekitar waktu ini, hal-hal yang sedang saya kerjakan ditunda, dan akhirnya saya memiliki banyak waktu, sehingga saya dapat terus melakukannya untuk waktu yang lama. Itu lebih mudah dengan sedikit gangguan, tetapi karena saya memilih hal-hal yang saya pikir menyenangkan, itu tidak terlalu sulit bahkan dengan gangguan pekerjaan. :)

Dan meskipun saya tidak menemukan sesuatu yang keren yang dapat saya ceritakan tentang Anda seperti Program Kepiting yang sadar diri, saya berhasil melakukannya dengan cukup baik.

Dan ... Dengan apa yang harus saya pelajari, PSE sayang, PSE sayang, dengan apa?

Untuk ini, saya menggunakan berbagai algoritma yang kebetulan saya sukai, ditambah berbagai hal yang saya ingin tahu jika Anda dapat melakukannya di F #, dan ketika saya kehabisan ide saya akan menangani hal-hal seperti 99 botol bir dan Project Euler masalah ...

Saya yakin Anda dapat menemukan banyak hal yang menarik bagi Anda yang relevan dengan FP; ia menawarkan segalanya mulai dari peningkatan hingga OOP yang membantu Anda menyatakan hal-hal sedikit lebih ringkas hingga memutar cara Anda akan memikirkannya sebelum menjadi bentuk yang tidak Anda kenal dan kemungkinan bahkan tidak memiliki model mental untuk mengekspresikan sebelum.

Tapi ... Ada lubang di model saya, PSE sayang ...

Dan inilah mengapa sangat penting bahwa, terutama di awal, tetapi benar-benar sepanjang waktu Anda belajar (dan bukankah itu selalu benar ketika Anda mempelajari sesuatu?) Anda setidaknya mengambil sedikit waktu antara masalah untuk membaca hal-hal yang tidak terkait tetapi masih FP dan waktu untuk membaca kode sumber yang ditulis oleh para ahli, lebih disukai menyelesaikan masalah yang sama atau serupa; serta penjelasan mereka tentang hal-hal ...

Dan sementara itu, Anda harus berusaha keras otak Anda untuk memahami semuanya, bukan dari perspektif lama Anda, tetapi dari dalam FP itu sendiri ... Di beberapa titik bagi saya, itu diklik, dan ... hal terbaik yang saya bisa mengaitkannya menjadi menjadi lebih atau kurang lancar berbahasa Belanda; pada titik tertentu saya berhasil menempatkan diri saya cukup dalam pola pikir (saya melakukannya melalui pencelupan, yang pada dasarnya adalah apa yang saya jelaskan di sini; membenamkan diri dalam FP daripada mencoba mempelajarinya hanya melalui "book larnin '" ...

Dan akhirnya saya lakukan; Saya berhasil menginternalisasi semuanya dan memutar otak saya sampai keluar mulai muncul FP / LINQ tanpa saya bahkan harus berusaha untuk menerjemahkannya kembali ke OOP. (Ya saya melakukan itu; Saya harus memiliki sesuatu untuk menggantungkan rok saya. Topi. Apa pun.)

Pikiran terakhir ...

Ya ampun, sepertinya kau kehilangan kemampuanmu untuk memikirkan tanda tangan pintarmu
judul bagian. Sayang sekali.

Teleconference masih cepat mendekat. Tampaknya jauh lebih besar sekarang.
> ya, ya, yah .. singkat dan semuanya. Saya melihat Anda berhasil kehilangan petunjuk itu.
 tutup panggilan, itu ... yah, ya, aku sedang ... OH TIDAK KEMBALI!
AAAAAAAHHHHHH !! [Lari menjerit, sekali lagi]

Teleconference masih cepat mendekat.
Entah bagaimana menyerupai Sir Lancyjohn Cleezewiz.
Itu hampir ada di tangan Anda.
> hei, cepat kembali! Saya punya percobaan untuk mencoba dengan Anda! (dan po-ta-to)

Anda dapat menemukan banyak info online tentang FP, secara alami. Hal utama adalah memahami konsep dasar, dan kemudian belajar menerapkannya. Sebagai contoh, pelajari tentang kekekalan, dan mengapa itu penting / berguna untuk FP. Saya sangat merekomendasikan belajar sedikit teori untuk mengikuti segala sesuatunya, seperti bagaimana FP murni bisa jauh lebih bisa menerima bukti formal. Ini adalah kekuatan pendorong di belakang nenek moyang F #, ML. YMMV tentu saja Anda mungkin seseorang yang bosan menangis dalam hal ini, banyak contoh, banyak percobaan dan kesalahan untuk melihat persis mengapa teknik yang digunakan adalah apa yang mereka akan membantu Anda memiliki 'Aha!' momen bola lampu

Jadi, saya akan membiarkannya sekarang. Semoga ini bermanfaat bagi seseorang. Saya ingin belajar lebih banyak tentang hal-hal spesifik, tetapi saya kehabisan waktu untuk saat ini. Mudah-mudahan saya akan menemukan waktu untuk kembali ke sana segera meskipun itu tampak menjadi minggu yang panjang bagi saya, jadi mungkin setidaknya akhir pekan.

<3 "Memperkenalkan GRUEBOL, pengganti sementara; hanya sampai SnozzML selesai. Seharusnya segera; Aku punya komite besar yang membantuku kali ini." --Grace Hopperwit Egghead, Famous Last Words , XX97 GUE <3


apa itu "sayang SO"?
nyamuk

adalah stack overflow sayang; seharusnya cocok dengan irama lagu 'Ada A Hole in the Bucket' xD
shelleybutterfly

ketika diposting di luar SO, ini tampaknya membuat poin Anda lebih sulit untuk dipahami - pertimbangkan mengedit akun untuk itu
gnat

derp! ya memang, sudah dilakukan. tyvm. :)
shelleybutterfly

jika ada yang punya saran untuk bagaimana meningkatkan jawaban saya, saya akan menghargainya .. apakah itu humor yang buruk? atau saran yang buruk? sebenarnya berdasarkan pengalaman saya jadi saya senang mengubahnya jika saya bisa membuatnya lebih bermanfaat. terima kasih;)
shelleybutterfly
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.