TDD - Outside In vs Inside Out

53

Apa perbedaan antara membangun aplikasi Outside In vs membangunnya Inside Out menggunakan TDD?

Ini adalah buku-buku yang saya baca tentang TDD dan pengujian unit:
Pengembangan Berbasis Tes: Dengan Pengembangan
Uji-Didorong: Panduan Praktis: Panduan Praktis
Solusi Dunia Nyata untuk Mengembangkan Kerangka Kerja PHP Berkualitas Tinggi dan Aplikasi
Pengembangan Berbasis Tes di Microsoft. NET
xUnit Pola Pengujian: Kode Uji Refactoring
Seni Pengujian Unit: Dengan Contoh di
Perangkat Lunak Berorientasi Objek Bersih Net , Dipandu oleh Pengujian ---> Yang ini sangat sulit untuk dipahami karena JAVA bukan bahasa utama saya :)

Hampir semua dari mereka menjelaskan dasar-dasar TDD dan pengujian unit secara umum, tetapi dengan sedikit menyebutkan berbagai cara aplikasi dapat dibangun.

Hal lain yang saya perhatikan adalah bahwa sebagian besar buku-buku ini (jika tidak semua) mengabaikan fase desain saat menulis aplikasi. Mereka lebih fokus pada penulisan test case dengan cepat dan membiarkan desain muncul dengan sendirinya.

Namun, saya menemukan paragraf dalam Pola Tes xUnit yang membahas cara orang mendekati TDD. Ada 2 sekolah di luar sana Di Luar vs. Di Dalam .

Sayangnya buku ini tidak menguraikan lebih lanjut tentang hal ini. Saya ingin tahu apa perbedaan utama antara 2 kasus ini.
Kapan saya harus menggunakan masing-masing?
Untuk pemula TDD mana yang lebih mudah dipahami?
Apa kelemahan dari masing-masing metode?
Apakah ada bahan di luar sana yang membahas topik ini secara khusus?

Songo
sumber
Kedua pendekatan tersebut dijelaskan di situs Pola Tes XUnit : xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html . Aneh bahwa mereka tidak ada di buku.
guillaume31

Jawaban:

45

Inside-Out dan Outside-In adalah istilah yang cukup langka, lebih sering saya mendengar / membaca tentang sekolah klasik dan sekolah London .

  • Inside-Out (Sekolah klasik, bottom-up ): Anda mulai pada tingkat komponen / kelas (dalam) dan menambahkan tes ke persyaratan. Ketika kode berkembang (karena refactoring), kolaborator baru, interaksi, dan komponen lainnya muncul. TDD memandu desain sepenuhnya.

  • Outside-In (sekolah London, top-down atau "TDD mockist" seperti yang disebut Martin Fowler): Anda tahu tentang interaksi dan kolaborator di muka (terutama yang di tingkat atas) dan mulai dari sana (tingkat atas), mengejek ketergantungan yang diperlukan. Dengan setiap komponen yang sudah jadi, Anda pindah ke kolaborator yang sebelumnya diejek dan mulai dengan TDD lagi di sana, membuat implementasi yang sebenarnya (yang, meskipun digunakan, tidak diperlukan sebelumnya berkat abstraksi ). Perhatikan bahwa pendekatan luar-masuk berjalan baik dengan prinsip YAGNI .

Tak satu pun dari pendekatan itu adalah satu-satunya ; mereka berdua memiliki tempat mereka tergantung pada apa yang Anda lakukan. Dalam solusi perusahaan besar, di mana bagian-bagian desain berasal dari arsitek (atau ada di muka) orang mungkin mulai dengan pendekatan "London style". Di sisi lain, ketika Anda menghadapi situasi di mana Anda tidak yakin bagaimana seharusnya kode Anda terlihat (atau bagaimana itu harus sesuai dengan bagian lain dari sistem Anda), mungkin lebih mudah untuk memulai dengan beberapa komponen kelas bawah dan membiarkannya berkembang seiring lebih banyak tes, refactoring dan persyaratan diperkenalkan.

Apa pun yang Anda gunakan, lebih sering situasional.

Untuk bacaan lebih lanjut, ada posting grup Google dengan diskusi yang agak menarik tentang bagaimana perbedaan ini (mungkin) berasal dan mengapa London mungkin bukan nama yang paling tepat.

km
sumber
2
Menarik. Bagaimana Anda mencapai kesimpulan bahwa di luar dalam TDD adalah "mockist" TDD? Saya sangat menyukai pemikiran dan desain Outside-In dan pengujian (lihat softwareonastring.com/2015/01/10/... ) namun artikel Fowler dengan tegas menempatkan saya dengan Fowler di kubu klasik. Meskipun mockist selalu menggunakan pendekatan luar-dalam, Anda tidak dapat memutarnya dan mengatakan bahwa desain dan pengujian luar-dalam adalah TDD mockist. Outside-in bisa dan sangat banyak dipraktikkan oleh TDD-ers klasik juga.
Marjan Venema
@jimmy_keen - Dengan luar-dalam, apakah Anda pada suatu saat mengganti ejekan dalam tes tingkat yang lebih tinggi dengan implementasi aktual yang dibuat kemudian? Atau apakah Anda membiarkannya sebagai dependensi yang diejek dan kemudian menjalankan seluruh kode produksi sebagai tes integrasi?
thehowler
1
Saya tidak setuju bahwa Classic / Mockist dan Inside-Out / Outside-In terkait. Mereka ortogonal. Anda dapat menggunakan Inside-Out / Outside-In dengan salah satunya.
Daniel Kaplan
Setuju dengan Daniel. Anda menyamakan dua taksonomi yang berbeda. Meskipun pengembangan luar-dalam sering dikaitkan dengan sekolah London (mockist), itu tidak selalu terjadi.
guillaume31
Saya tidak berpikir ini adalah deskripsi yang benar dari proses luar-dalam. Ini tentang pengujian dari antarmuka publik tanpa menghubungkan ke internal, sebanyak mungkin.
mcintyre321
15

Jawaban Singkat: Seperti biasa itu akan tergantung pada preferensi pengkodean Anda dan pendekatan tim.

Pengkodean dalam ke luar sangat bagus karena Anda selalu memiliki sesuatu yang berfungsi. Kelemahannya adalah tidak selalu membantu Anda mencapai tempat yang sangat berbeda. Lebih sulit memetakan arah seperti ini. Demikian pula, menulis kode di luar memiliki kelemahan karena tidak selalu memiliki manfaat dari pengembangan berulang yang cepat, dan tidak harus melihat semua peluang dan pola yang mungkin muncul dari jauh di dalam struktur kode.

Saya mulai percaya bahwa kedua gaya pengembangan itu penting , dan bahwa sebenarnya bermanfaat untuk memiliki campuran gaya dalam sebuah tim. Idenya adalah bahwa dalam ke luar sangat bagus untuk membuat blok bangunan, dan bagian luar dalam pemikiran menyediakan struktur dan arah bentuk.

Sebagian dari alasan saya berasal dari aliran pemikiran yang sangat populer yang saat ini mempromosikan pengembangan berulang, yang seringkali identik dengan pengembangan dari dalam ke luar. Saya percaya pengembangan berulang itu bagus ketika Anda tidak perlu melangkah terlalu jauh. Tetapi saya berpikir bahwa pemikiran besar, yang bertentangan dengan proses berulang murni sangat berharga untuk jenis inovasi tertentu dan untuk sampai ke tempat yang kurang jelas. Dikelola dengan benar, dalam dan luar bersama-sama bisa menjadi kombinasi yang sangat efektif.

EL Yusubov
sumber
8

Anda harus menambahkan Prinsip Agile, Pola dan Praktek di C # ke daftar itu. Saya tidak tahu mengapa dia menempel pada "di C #" pada akhirnya. Buku-buku itu bukan bahasa sama sekali dan satu-satunya alasan itu tidak mendapatkan 5 bintang di amazon adalah dari orang-orang yang kecewa dengan C # -ness dari contoh-contohnya.

Penulis, menganjurkan bahwa sedapat mungkin Anda harus mencoba menulis kode di luar dan sangat bergantung pada desain evolusi, dan saya setuju dengan pernyataannya. Alasannya adalah bahwa saat kami menambahkan fungsionalitas, desain kami akan selalu berkembang. Jika kita mulai dengan komponen tingkat rendah ketika fitur ditambahkan, kita akan menyadari komponen-komponen itu tidak melakukan apa yang kita inginkan, atau hal-hal yang perlu dipindahkan. Ini bisa menjadi agak mahal terutama jika setiap kali Anda memindahkan fungsionalitas dari satu kelas ke kelas lain, Anda perlu melakukan langkah yang sama di semua proyek unit test.

Di sisi lain, jika Anda menentukan apa yang seharusnya dilakukan aplikasi Anda, Anda membuat kode untuk antarmuka eksternal. Ketika fitur ditambahkan dan kode yang sedang diuji bertambah besar ukurannya, Anda mengubah aplikasi menjadi lebih banyak kelas, tetapi sementara upaya refactoring ini berlangsung, pengujian unit asli yang Anda tulis tetap valid. Jadi, Anda mulai sepenuhnya dari luar dan melanjutkan refactoring ke kelas-kelas tingkat yang lebih rendah dan lebih banyak, sambil menambahkan tes unit tambahan untuk kelas-kelas batin tersebut, tetapi Anda jarang harus bergerak dan menulis ulang tes unit Anda.

Namun, jika Anda mengidentifikasi subsistem tingkat rendah tertentu yang dibutuhkan aplikasi Anda (dan mungkin perusahaan Anda sudah memiliki kebutuhan untuk subsistem tersebut di aplikasi lain), ini akan menjadi waktu untuk memulai dengan blok penyusun tingkat rendah terlebih dahulu dan kemudian bangun aplikasi diatas itu.

DXM
sumber
7

Seperti yang saya lihat, konsep pengembangan luar-dalam benar-benar menyebar pada 2 level. Gerard Meszaros secara singkat menggambarkan mereka sebagai " desain luar-dalam " dan "luar-dalam / luar- coding ".

  • Level pertama adalah level organisasi dan proses. Desain luar-dalam dimaksudkan sebagai kebalikan dari top-down (air terjun / taylorist) dan bottom-up. Dengan pendekatan luar-dalam, kami fokus pada perspektif pengguna akhir. Kita mulai dengan tes cerita, tes ATDD atau BDD dan pergi "ke dalam" menyimpulkan tes teknis dan kode. Jadi desain luar-dalam biasanya adalah apa yang akan Anda lakukan dalam konteks Agile. Dan North memiliki pembicaraan besar tentang pendekatan BDD, top-down, bottom-up dan luar-dalam.

  • Tingkat kedua adalah teknis dan berkaitan dengan lapisan aplikasi. Pengodean luar-dalam pada dasarnya berarti mulai dari UI dan masuk ke lapisan tengah (biasanya lapisan bisnis / domain). Ini dimaksudkan sebagai kebalikan dari pengkodean dalam-luar yang dimulai dari lapisan tengah dan pengkodean lapisan eksternal terakhir.

Jadi Anda bisa memiliki desain luar-dalam dengan pengkodean luar-dalam atau pengkodean dalam-luar.

Di mana saya tidak setuju dengan Meszaros adalah ketika dia mengaitkan pengkodean luar-dalam dengan pengujian integrasi, dengan alasan bahwa dalam konteks luar-dalam "kita tidak benar-benar menguji perangkat lunak luar dengan mengasingkan perangkat lunak dalam". Tapi saya percaya tidak ada yang mencegah Anda melakukannya. Anda dapat dengan sempurna memilih untuk menguji objek lapisan luar Anda dengan mengejek objek lapisan dalam bahkan jika kode produksi untuk itu sudah ada. Anda hanya perlu menambahkan antarmuka dan tiruan di atas objek konkret yang ada alih-alih menulis antarmuka, mengejek mereka dan kemudian membuat implementasi nanti seperti yang akan Anda lakukan dengan pengkodean luar-dalam.

Dengan kata lain, TDD gaya mockis atau klasisis merupakan masalah orthogonal terhadap pengkodean luar-dalam / luar-luar. Anda dapat dengan sempurna menggunakan gaya mockist bersama dengan pendekatan luar ke dalam. Alasan di balik ini adalah bahwa gaya mockist / klasisis adalah tentang ketergantungan kode sedangkan pengkodean luar-dalam / dalam-luar adalah tentang lapisan aplikatif .

Hal penting lainnya adalah bahwa dependensi tidak hanya melintasi lapisan, mereka juga ada di antara objek di lapisan yang sama. Misalnya, Anda mungkin ingin memulai dengan satu objek di lapisan pusat bisnis Anda (pendekatan luar-dalam) dan menggunakan tiruan untuk mengisolasi objek Anda dari objek-objek lapisan bisnis lain tempat ia berbicara. Ini sering terjadi dengan IoC - abstraksi yang bergantung pada objek Anda sering dinyatakan dalam lapisan yang sama, tetapi implementasi konkret berada di lapisan yang berbeda.

Robert "Paman Bob" Martin secara singkat menyebutkan pengkodean dalam-luar dan bagaimana itu tidak selalu bertentangan dengan arsitektur yang dipisahkan dalam posnya " Arsitektur Bersih ".

guillaume31
sumber