Penulis Topik: VB atau C#?  (Dibaca 3660 kali)

0 Anggota dan 1 Pengunjung sedang melihat topik ini.

Offline Èxsharaèn

  • Pölisia mar Ranch-i-ru
  • Administrator
  • Lv 9 Petualang senior
  • ************
  • Tulisan: 5.650
  • Karma: 8
  • Jenis kelamin: Pria
  • Veni, veni, venias; ne me mori facias...
  • Sistem Operasi:
  • Windows 8/Server 2012 Windows 8/Server 2012
  • Peramban:
  • Chrome 26.0.1410.64 Chrome 26.0.1410.64
  • Bergabung sejak: 14/10/2006
    YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • RPG Fantasy Web Indonesia
VB atau C#?
« pada: 22 April 2013, 01:08:28 »
Beberapa hari terakhir aku dapat pertanyaan dari stash. Seperti yang sudah kita ketahui bersama, dia sedang buat program untuk tokonya menggunakan VB. Nah, dia punya ide untuk menggunakan tablet Android. Berhubung tablet dan desktop sementara ini dua dunia yang berbeda (apalagi Android dan Microsoft), dia pingin tahu, bisa nggak sih sebenarnya dia bikin aplikasi yang jalan di dua-duanya. Aku sudah cari dan jawabnya bisa (tapi bukan itu inti topik ini; yang tertarik bisa buat topik baru), tapi menggunakan C#.

Muncullah pertanyaan sekarang: apa sih bedanya VB dan C#? Mana yang lebih baik?

Kalau dari pengalaman pribadiku, aku mengalami zaman C++ dan VB 6 Microsoft. Dari dua bahasa itu, aku lebih suka VB 6 karena C++ sepertinya ribet sekali, dan VB 6 bahasanya lebih mudah dimengerti. Setelah itu, di kuliah aku kenal Java. Bahasa ini awalnya menyenangkan, tapi setelah sekian lama ternyata lebih aneh dari C++. Setelah era .NET hadir, muncullah bahasa baru, C#, yang baru kupelajari sekitar tahun 2008. Entah kenapa, bahasa ini menarik sekali. Walaupun secara sintaks mirip dengan Java (dan kenyataan bahwa Java terinspirasi dari C++ berarti C# juga mirip dengan C++, yang tidak terlalu "manusiawi" dibandingkan VB), aku menemukan bahwa C# lebih kuat daripada VB.

Sebelum VB fans ngomel, iya memang 90% yang bisa dilakukan C# juga bisa dilakukan VB :D Jadi, topik ini tidak bermaksud membuat perang suci baru antara VB dan C# (percaya atau nggak, perang kaya gini hampir sama "sucinya" dengan perang agama).

Perbedaan antara VB dan C# terutama terletak pada sintaks, beberapa mungkin lebih suka VB daripada C# karena lebih Inggris. Contoh saja deh (semoga sintaks VB benar, aku sudah lama sekali ga nyentuh bahasa itu):

Untuk deklarasi variabel atau objek baru, VB melakukannya seperti ini:
Kode: [Pilih]
Dim area As Integer
Dim arshes As New Player

C#? Sama nggak terbacanya oleh orang awam seperti C++ :D
Kode: [Pilih]
int area;
Player arshes = new Player();

Kondisi? VB juga lebih Inggris:
Kode: [Pilih]
If age > 20 And age < 50 Then
txtResult.Text = "Adult"
End If
If gender = "M" Then
txtGender.Text = "Male"
Else
txtGender.Text = "Female"
End If

C#? Kelihatan lebih kriptik:
Kode: [Pilih]
if (age > 20 && age < 50)
{
txtResult.Text = "Adult";
}
if (gender == "M") // atau bahkan lebih ribet: if (gender.Equals("M"))
{
txtGender.Text = "Male";
}
else
{
txtGender.Text = "Female";
}

Select Case-nya VB bahkan lebih powerful dibanding switch-nya C#. Konversi angka? VB lebih toleran. Kalau mau disebutkan lagi, banyak daftarnya. Garis besarnya, C# ini (sesuai namanya, tajam) lebih rewel daripada VB. Tapi, berhubung kita bicara VB.NET dan C#, yang dua-duanya adalah bahasa yang dibangun di atas .NET Framework, secara fungsional mereka berdua nyaris ga ada bedanya :)

Jadi, silakan dipilih sendiri bahasa yang mau dipakai, apakah itu VB atau C#. Bagi mereka yang pernah belajar C++ atau Java, C# mungkin lebih mudah karena sintaksnya sangat mirip. Bagi mereka yang belum pernah mengenal pemrograman sama sekali, VB mungkin lebih alami. Untuk pemrograman sederhana (misal kasir, inventaris toko), VB sudah cukup. Untuk pemrograman yang agak kompleks (misal game), C# lebih dianjurkan.

Kalau masih nggak yakin, coba cek beberapa halaman berikut:
What makes C# better than VB? (Social MSDN forum)
VB or C#?
Comparison of C# and Visual Basic.NET (Wikipedia)
Jangan lupa ikutan serunya petualangan Our Journey!
~ A, èxshna il utnön qu our journey shallaran a èndh... ~

Profiles
WAYN http://Exsharaen.wayn.com
About.me http://about.me/hoshiro.exsharaen

Offline Èxsharaèn

  • Pölisia mar Ranch-i-ru
  • Administrator
  • Lv 9 Petualang senior
  • ************
  • Tulisan: 5.650
  • Karma: 8
  • Jenis kelamin: Pria
  • Veni, veni, venias; ne me mori facias...
  • Sistem Operasi:
  • Windows 8/Server 2012 Windows 8/Server 2012
  • Peramban:
  • Chrome 26.0.1410.64 Chrome 26.0.1410.64
  • Bergabung sejak: 14/10/2006
    YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • RPG Fantasy Web Indonesia
Function/Sub = Method
« Jawab #1 pada: 23 April 2013, 12:39:22 »
Sekalian jawab beberapa pertanyaannya stash, kepanjangan ngetik di BBM :P

Function/Sub = Method
Kalau di VB kita kenal dua jenis fungsi, yaitu function (yang mengembalikan suatu nilai) dan sub (yang tidak mengembalikan apa-apa), di C# semuanya dipanggil dengan satu nama: method (sebenarnya di VB pun sub adalah function). Cara bikinnya sama saja seperti di VB, tulis di dalam blok class.

Sintaks untuk Sub:
Kode: [Pilih]
void NamaMethod([tipe param1, tipe param2, ...])
{
    // isi method di sini...
    // return; bisa dipakai kalau mau segera keluar dari method tanpa harus menjalankan baris sisanya (mirip dengan break pada loop). Walaupun namanya return, dia tidak mengembalikan apa-apa di method yang bertipe void (dan ini sah)
}
// Contoh (agak jarang sih method yang tipenya void...)
void ConnectToDb(string username, string password)
{
    // asumsi connection string dan objek conn sudah ada
    if(conn != null) conn = new SqlConnection(connectionString);
// blok Try-Catch-Finally di C# kurang lebih sama
    try
    {
        conn.Open();
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        if(conn.State == ConnectionState.Open) conn.Close();
    }
}

Untuk function, tinggal pindahkan tipe return value (setelah As terakhir) ke paling depan (sebelum nama fungsi). Jadi, kalau di VB bentuknya begini:
Kode: [Pilih]
Function NamaFungsi([param1 As tipe, param2 As tipe [= nilaiDasar], ...]) As tipeReturnValue
    ' isi fungsi
    Return myValue
End Function
di C# jadi begini:
Kode: [Pilih]
tipeReturnValue NamaFungsi([tipe param1, tipe param2, ...])
{
    // isi fungsi
    return myValue;
}
// Contoh: fungsi menghitung luas persegi panjang
double HitungLuas(double panjang, double lebar)
{
    return panjang * lebar;
}
// Sayangnya, C# tidak punya fitur default value untuk parameter, jadi harus diakali dengan bantuan overload: menulis ulang method yang sama tapi dengan signature (deklarasi) yang berbeda, seperti ini.
// Hitung luas persegi menggunakan bantuan method HitungLuas
double HitungLuas(double sisi)
{
    return HitungLuas(sisi, sisi);
}

Untuk persamaan ByVal dan ByRef di C# aku tinggalkan dulu untuk sementara sampai dibutuhkan lagi.

EDIT:
Akhirnya butuh juga... ByRef di VB mengizinkan kita mengubah nilai parameter suatu function/sub dan perubahannya tercermin di argumen. Bingung? Coba sub ini deh:

Kode: [Pilih]
Sub CobaUbah(ByRef angka As Integer)
    angka = 10
End Sub

' Lalu lakukan ini, misalkan di Form_Load():
Dim intAngka As Integer
intAngka = 5;
CobaUbah(intAngka)
MessageBox.Show(intAngka) ' hasilnya 10 bukan 5

Proses passing argumen seperti ini dinamakan passing by reference (makanya namanya ByRef). Proses satunya bernama passing by value, yang merupakan sifat dasar argumen kalau tidak ada kata bantu apa-apa (bahkan di VB ByVal pun tidak harus ditulis). Passing by value tidak menyebabkan argumen berubah kalau parameter berubah. Terminologi lebih lanjut bagi yang tertarik bisa dibaca di MSDN.

C# juga punya fitur passing by reference, namanya ref dan out. Nah lho... bedanya apa? Kalau parameter didefinisikan sebagai ref, argumen yang mau diberikan ke method itu harus sudah punya nilai terlebih dahulu, tapi masalah nanti parameter itu bakal berubah atau tidak di dalam method, ref tidak peduli. Sebaliknya, parameter yang bersifat out harus berubah di dalam method nilainya, tapi argumennya tidak harus punya nilai terlebih dahulu. Bingung ya :P contoh saja deh:

Kode: [Pilih]
// Contoh parameter ref
void Method1(ref int angka)
{
    angka = 2; // coba comment baris ini dan lihat hasilnya
}

// Contoh parameter out
// Method ini terpaksa dipisah dari Method1 karena C# tidak mengizinkan overload kalau parameternya hanya berbeda ref/out
void Method2(out int angka)
{
    angka = 2; // coba comment baris ini dan lihat hasilnya (kemungkinan besar error)
}

// Coba ini di suatu tempat, misalnya Form_Load
int x, y;
x = 5; // coba comment baris ini dan lihat hasilnya (kemungkinan besar error)
y = 10; // coba comment baris ini dan lihat hasilnya
Method1(ref x); // kata ref harus eksplisit dituliskan, kalau tidak C# akan komplain
Method2(out y); // kata out harus eksplisit dituliskan, kalau tidak C# akan komplain
// Tampilkan x dan y, lihat hasilnya

Beberapa percobaan awal akan memberikan error bahkan sebelum dijalankan (aku biasa menyebutnya "error cacing" karena muncul garis zig-zag merah atau biru mirip cacing di baris yang error), jadi silakan bereksperimen sendiri dan tentukan mana yang benar :)

Kalau dilihat, pemanggilan method di C# jadi tampak aneh. Benar, tapi secara eksplisit C# memberi tahu kita bahwa argumen itu ada kemungkinan nilainya berubah kalau menggunakan out/ref. Bandingkan sub ini di VB:

Kode: [Pilih]
Sub Calculate(ByVal rate As Double, ByRef debt As Double)
    debt = debt + (debt * rate / 100)
End Sub

' Manggilnya:
Calculate(lowRate, debtWithInterest)

Kalau tidak hati-hati, kita bisa lupa bahwa debtWithInterest itu sifatnya ByRef, akibatnya nilainya bisa diubah oleh Calculate. Bandingkan method yang sama di C#:

Kode: [Pilih]
void Calculate(double rate, ref double debt)
{
    debt = debt + (debt * rate / 100);
}

// Manggilnya: (asumsi debtWithInterest sudah punya nilai sebelum method ini dipanggil)
Calculate(lowRate, ref debtWithInterest);

Jelas kan bahwa debtWithInterest itu ref sehingga bisa berubah? Ini mengurangi sakit kepala gara-gara nilai "ajaib" yang tiba-tiba mengubah suatu variabel tanpa kita sadari :)
« Edit Terakhir: 23 April 2013, 08:23:09 oleh Èxsharaèn »
Jangan lupa ikutan serunya petualangan Our Journey!
~ A, èxshna il utnön qu our journey shallaran a èndh... ~

Profiles
WAYN http://Exsharaen.wayn.com
About.me http://about.me/hoshiro.exsharaen

Offline Èxsharaèn

  • Pölisia mar Ranch-i-ru
  • Administrator
  • Lv 9 Petualang senior
  • ************
  • Tulisan: 5.650
  • Karma: 8
  • Jenis kelamin: Pria
  • Veni, veni, venias; ne me mori facias...
  • Sistem Operasi:
  • Windows 8/Server 2012 Windows 8/Server 2012
  • Peramban:
  • Chrome 26.0.1410.64 Chrome 26.0.1410.64
  • Bergabung sejak: 14/10/2006
    YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • RPG Fantasy Web Indonesia
Module = Static class
« Jawab #2 pada: 23 April 2013, 01:07:55 »
Nah ini pertanyaan yang cukup susah dijawabnya. Kalau di VB kita bisa bikin modul dan menaruh apapun di sana, bagaimana dengan C#?

Sayangnya, C# tidak mengenal modul. Karena C# adalah bahasa PBO (OOP), semuanya harus berbentuk objek, termasuk apapun yang mau digunakan secara global (= tujuan membuat modul di VB). Memang mengglobalkan suatu variabel harus dilakukan dengan hati-hati (lebih sulit diprediksi siapa yang mengubah variabel tersebut, daripada kalau variabel tersebut "dibatasi" oleh kehadiran class), tapi ada kalanya kita perlu sesuatu yang tidak terikat dalam konteks apapun.

Solusinya, gunakan static class. Kelas statis adalah kelas yang tidak bisa dibuat objeknya (menggunakan perintah new), jadi dalam satu sesi aplikasi hanya ada satu kelas tersebut. Contoh kelas statis di .NET adalah System.Math.

Cara buatnya:
1. Tambahkan kelas baru ke projek (klik kanan di projek > Add > New Class...). Beri nama terserah.
2. Tambahkan kata static ke signature kelas itu. Tidak ada batasan letaknya harus di mana, selama dia mendahului class; biasanya diletakkan setelah scope identifier public. Contoh:
Kode: [Pilih]
public static class DbHelper
{
}

Kelas ini hanya menerima static member, jadi apapun yang dibuat di dalamnya harus punya kata static. Karena kelas ini nantinya bisa diakses siapa saja, logisnya semua member di dalamnya public. Contoh:
Kode: [Pilih]
public static class TemperatureConverter
{
    public static double CelsiusToFahrenheit(string temperatureCelsius)
    {
        // Convert argument to double for calculations.
        double celsius = Double.Parse(temperatureCelsius);

        // Convert Celsius to Fahrenheit.
        double fahrenheit = (celsius * 9 / 5) + 32;

        return fahrenheit;
    }

    public static double FahrenheitToCelsius(string temperatureFahrenheit)
    {
        // Convert argument to double for calculations.
        double fahrenheit = Double.Parse(temperatureFahrenheit);

        // Convert Fahrenheit to Celsius.
        double celsius = (fahrenheit - 32) * 5 / 9;

        return celsius;
    }
}

Cara pakainya? Tinggal tuliskan nama kelas statis ini, diikuti titik dan apapun yang mau diakses. Contoh, untuk menggunakan kelas TemperatureConverter di atas:
Kode: [Pilih]
public class TestTemperatureConverter
{
    public static void Main()
    {
        Console.WriteLine("Please select the convertor direction");
        Console.WriteLine("1. From Celsius to Fahrenheit.");
        Console.WriteLine("2. From Fahrenheit to Celsius.");
        Console.Write(":");

        string selection = Console.ReadLine();
        double F, C = 0;

        switch (selection)
        {
            case "1":
                Console.Write("Please enter the Celsius temperature: ");
                F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine());
                Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                break;

            case "2":
                Console.Write("Please enter the Fahrenheit temperature: ");
                C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine());
                Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                break;

            default:
                Console.WriteLine("Please select a convertor.");
                break;
        }
    }
}
Catatan: Untuk mencoba contoh ini, buat projek Console Application baru. Kode ini kumodifikasi dari MSDN dengan membuang semua System. karena normalnya projek baru sudah using System;.

static juga bisa digunakan untuk kelas biasa, tapi penjelasan untuk itu kutinggalkan dulu sampai dibutuhkan nanti.
Jangan lupa ikutan serunya petualangan Our Journey!
~ A, èxshna il utnön qu our journey shallaran a èndh... ~

Profiles
WAYN http://Exsharaen.wayn.com
About.me http://about.me/hoshiro.exsharaen

Offline Èxsharaèn

  • Pölisia mar Ranch-i-ru
  • Administrator
  • Lv 9 Petualang senior
  • ************
  • Tulisan: 5.650
  • Karma: 8
  • Jenis kelamin: Pria
  • Veni, veni, venias; ne me mori facias...
  • Sistem Operasi:
  • Windows 8/Server 2012 Windows 8/Server 2012
  • Peramban:
  • Chrome 26.0.1410.64 Chrome 26.0.1410.64
  • Bergabung sejak: 14/10/2006
    YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • RPG Fantasy Web Indonesia
Automatic type cast? No, no, no!
« Jawab #3 pada: 23 April 2013, 07:44:22 »
Pertanyaan baru dari stash:

Kutip dari: stash
Aku ada integer intAngka. Aku mau tampilin di message box. Kalau VB bisa langsung MessageBox.Show(intAngka). Tapi di C# kok keluar error, intAngka bukan string

Selamat datang di ketatnya dunia C# :D di C#, ekspresi seperti itu tidak dibenarkan. Kenapa? Argumen pertama dari method Show itu adalah sebuah string, teks yang mau ditampilkan di message box. Tapi, yang dimasukkan adalah sebuah int. Sama jenisnya? Nggak :) Karena itu, C# mengharuskan kita melakukan type cast manual. Ribet? Awalnya mungkin, tapi secara tidak langsung ini menjaga data kita tetap konsisten, jadi kita tidak perlu khawatir macam-macam.

Ekspresi tadi di C# jadinya gini:
Kode: [Pilih]
MessageBox.Show(intAngka.ToString());

Nyaris apapun bisa kita .ToString(). Kalau kebalikannya bagaimana? Dari string mau diganti ke angka, misalkan menerima input dari txtAngka dan memasukkannya ke variabel intAngka.

Kode: [Pilih]
intAngka = int.Parse(txtAngka.Text);

Rata-rata tipe data primitif (int, long, float, double) punya metode Parse() untuk mengubah string menjadi yang kita butuhkan. Ada cara lain, yaitu menggunakan kelas statis Convert. Silakan dicari metode ToInt32 (int), ToInt64 (long), ToFloat (float), ToDouble (double), dan sebagainya di kelas tersebut; mereka bahkan terima lebih banyak jenis argumen (Parse harus string). Tapi awas! Metode ini berasumsi argumen yang dia terima (string) pasti bisa diubah ke tipe data yang bersangkutan. Kalau tidak bisa, kita akan dapat error (bahasa .NET: exception) FormatException. Atau, kalau nilainya kegedean/kekecilan, kita kena OverflowException.

Untuk menghindari hal ini, khusus tipe data primitif, mereka menyediakan metode lain, yaitu TryParse. Metode ini membutuhkan dua argumen. Argumen pertama adalah string yang mau kita coba ubah ke tipe data yang kita mau. Argumen kedua, sifatnya out, adalah variabel yang mau kita beri nilai konversi. Kalau sukses, variabel itu akan berisi hasil konversi dan metode ini mengembalikan nilai true. Kalau tidak, false.

Contoh:
Kode: [Pilih]
int intAngka;
bool valid = int.TryParse(txtAngka.Text, out intAngka);
if (valid) // intAngka pasti sudah ada isinya, asalkan sukses
{
// Lanjutkan proses...
}
else
{
MessageBox.Show("Masukkan hanya angka!");
}

Metode ini merapikan pendekatan try-catch metode Parse:
Kode: [Pilih]
int intAngka;
try
{
intAngka = int.Parse(txtAngka.Text);
// Lanjutkan proses...
}
catch (FormatException fex)
{
MessageBox.Show("Masukkan hanya angka!");
}
// blok catch yang ini opsional...
catch (OverflowException oex)
{
MessageBox.Show("Masukkan hanya antara 0 hingga 10!"); // tentu saja batas int tidak sekecil ini :D
}

Yang belum pernah ketemu blok try-catch, aku jelaskan nanti.
Jangan lupa ikutan serunya petualangan Our Journey!
~ A, èxshna il utnön qu our journey shallaran a èndh... ~

Profiles
WAYN http://Exsharaen.wayn.com
About.me http://about.me/hoshiro.exsharaen

Offline Èxsharaèn

  • Pölisia mar Ranch-i-ru
  • Administrator
  • Lv 9 Petualang senior
  • ************
  • Tulisan: 5.650
  • Karma: 8
  • Jenis kelamin: Pria
  • Veni, veni, venias; ne me mori facias...
  • Sistem Operasi:
  • Windows 8/Server 2012 Windows 8/Server 2012
  • Peramban:
  • Chrome 26.0.1410.64 Chrome 26.0.1410.64
  • Bergabung sejak: 14/10/2006
    YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • RPG Fantasy Web Indonesia
Notasi Hungaria
« Jawab #4 pada: 23 April 2013, 08:58:54 »
Perdebatan ini panjang sekali umurnya, jadi aku nggak akan nambah lagi di sini :D adakah yang memperhatikan bahwa ketika aku nulis kode C# untuk deklarasi variabel, ada yang aneh?

Kode: [Pilih]
int intAngka;

Kita mendeklarasikan variabel bertipe int, tapi masih ngasih prefiks int ke nama variabel? Menambahkan prefiks ke variabel, seperti yang aku ajarkan ke stash dan pada contoh, dinamakan notasi Hungaria. Notasi ini diciptakan oleh salah satu programmer Microsoft, dan sempat populer. Tapi, begitu Microsoft merilis .NET, kalimat ini bisa ditemui di semua artikel Naming Conventions:

Kutip
Do not use Hungarian notation.

Secara pribadi, aku sudah tidak lagi menggunakan notasi ini, kecuali untuk nama kontrol untuk mempermudah ingatan, karena deklarasi kontrol disembunyikan di berkas terpisah (beda dengan variabel yang kita deklarasikan sendiri). Bahkan, kadang-kadang kalau kontrol itu kudeklarasikan melalui kode karena kebutuhan, aku masih pakai notasi Hungaria. Atau, untuk beberapa objek yang tipenya kompleks, aku masih pakai notasi Hungaria. Jadi, style kodeku sekarang begini:

Kode: [Pilih]
int angka; // bukan lagi intAngka
double luas; // bukan lagi dblLuas
string query;
SqlConnection conn = new SqlConnection(); // kecuali aku tidak yakin persis apa tipe Connection ini, bisa ada prefiks untuk conn, misalkan orclConn untuk OracleConnection atau sqlConn untuk SqlConnection, tapi jarang sekali ada yang menggunakan lebih dari satu tipe Connection dalam satu projek
DataSet dsUser = new DataSet(), dsMessages = new DataSet(); // user dan messages saja sebetulnya cukup :)
TextBox txtNama = new TextBox();
txtNama.Text = String.Empty;

Secara umum, pengguna VB pun juga bisa meninggalkan notasi ini, karena toh Visual Studio bisa memberi tahu kita tipe data sesuatu. Pengguna C# otomatis lama-kelamaan akan terlatih mengingat tipe data variabelnya karena keketatan C# :)

Jadi, baik untuk VB maupun C#, terserah apakah masih mau menggunakan notasi Hungaria.

Bacaan lebih lanjut:
http://www.joelonsoftware.com/articles/Wrong.html (agak di tengah masalah notasi Hungaria)
Diskusi di Stack Overflow
Jangan lupa ikutan serunya petualangan Our Journey!
~ A, èxshna il utnön qu our journey shallaran a èndh... ~

Profiles
WAYN http://Exsharaen.wayn.com
About.me http://about.me/hoshiro.exsharaen

 

Dengan Jawab-Cepat Anda dapat menggunakan kode buletin board dan smiley seperti tulisan normal, tapi jauh lebih menyenangkan.

Peringatan: topik ini belum dituliskan setidaknya 120 hari.
Kecuali Anda yakin ingin menjawabnya, harap pertimbangkan untuk memulai sebuah topik baru.

Nama: Email:
Anti-spam: complete the task