TDD ve kapsülleme öncelikli çatışma

3 Cevap php

Ben sadece benim projelerde TDD uygulamaya başladı. Php / zend / mysql ve test için phpunit / DbUnit kullanarak artık bir proje geliştiriyorum. Ben sadece kapsülleme fikrine dalıp bir bit ve tahrik testi yaklaşımı değilim. Kapsülleme arkasında benim fikrim birkaç nesne işlevlere erişim gizlemektir. (Onu aramak için bir kamu işlevi oluşturmak sürece) daha net yapmak için, özel ve korumalı fonksiyonları doğrudan sınanabilir değildir.

Ben sadece onları test edebilmek için kamusal işlevleri için bazı özel ve korumalı fonksiyonları dönüştürme sonunda. Gerçekten mikro fonksiyonu testability yol vermek için kapsülleme ilkelerini ihlal ediyorum. Bu bunu yapmanın doğru yolu nedir?

3 Cevap

TDD çevrelerde bu oldukça standart bir cevabı vardır. Işlevselliğe işlevselliği ile hem gizli ve doğrudan test yapmanız gerekir sprout a class istediğiniz bir sınıf varsa. Bu TDD tasarım geliştirir nasıl büyük bir örnektir.

Orijinal sınıfta, gereksiz işlevselliği gitmiş olduğundan, filizlenmiş sınıf içinde sarılmış, yani özgün sınıf 'tasarımı basittir, ve Single Responsibility Principle daha uygundur. Filizlenmiş sınıfında, ekstre işlevselliği onun raison d'etre, kamu olmak için bu nedenle uygun olan ve bu nedenle test sadece bir değişiklik olmadan test edilebilir olması.

Orada saygı Carl Manaster en güzel cevap, en azından Carl önerdi yolda başlamadan önce düşünmelisiniz bazı dezavantajları vardır.

Hangi en önemli şudur: Biz değişiklik yayılma büyük olasılık taşıyan potansiyel bağımlılıkları sayısını en aza indirmek için kapsüllemeyi kullanın. Senin durumunda, size sınıf içinde özel yöntemleri kapsüllü var: diğer sınıflar için kullanılabilir değildir ve bu nedenle onlara hiçbir potansiyel bağımlılıkları vardır: Eğer onlara yaptığınız değişikliklerin maliyeti minimize ve diğer yayılma düşük probablility vardır sınıflar.

(Eğer bunları test edebilirsiniz böylece) Carl yeni bir sınıfın içine sınıfından bazı özel yöntemler hareketli, ve bu yöntemler kamu yapma anlaşılacağı gibi görünüyor. (Bu arada, neden sadece orijinal sınıfta onları kamu yapmak değil mi?)

Bunu yaparak, başka bir sınıf bunları kullanarak almalısınız potansiyel bu yöntemleri chaging maliyeti artacak, bu yöntemlerin diğer sınıfların 'oluşturan bağımlılıkları engeli kaldırın.

Bu aşağı tarafı minör ve özel yöntemler test edememek ödemek için değerli bir fiyat yargıç, ama en azından bunun farkında olabilir. Durumlarda küçük bir sayıda, gerçekten değerli olabilir, ancak kod tabanı boyunca bu enstitü ise o zaman büyük ölçüde bilinmeyen bir dereceye kadar bakım döngüsünün maliyeti artan, bu bağımlılıkları oluşturacak olasılığını artırmak gerekir.

Bu nedenlerden dolayı, ben, onun öneri olduğunu Carl katılmıyorum "... TDD tasarım geliştirir nasıl büyük bir örnek."

Dahası, "gereksiz işlevselliği filizlenmiş sınıfı içinde sarılı, gitti, bu yüzden özgün sınıf 'tasarım basit ve tek sorumluluk ilkesi daha uygundur ki, orijinal sınıfında.", Devletler

Ben taşınıyor işlevselliği, tüm olmadığını iddia ediyorum Ayrıca, "basit," iyi tanımlanmış değildir "Yabancı".: Kesinlikle bir sınıfın basitlik büyüklüğü ile ters orantılı olduğu durumda olabilir ama bu değil basit-olası sınıfların bir sistem olabildiğince basit bir sistem olacak demek: Bu durumda olsaydı, tüm sınıflar sınıfların büyük bir sayı olurdu bir yöntem ve bir sistem sadece içerecektir; çoklu-yöntemleri-içinde-sınıfların bu hiyerarşik tabakasının uzaklaştırılması, iddia edilebilir ki, sistemi çok daha karmaşık hale getirecektir.

Tek Sorumluluk Prensibi (SRP), ayrıca, herkesin bildiği subjektif ve gözlemci soyutlama düzeyinde tamamen bağlıdır. Bu sınıftan bir yöntem otomatik kaldırma SRP olan uygunluğunu iyileştirir her durum değildir. Bir Yazıcı sınıfı, 10 yöntemleri ile, sınıfının soyutlama düzeyinde baskı tek sorumluluğu vardır. Bu yöntemlerden biri checkPrinterConnected olabilir () ve bir checkPaper (olabilir); yöntem düzeyinde, bu açıkça ayrı sorumlulukları vardır, ancak bunlar otomatik olarak sınıf daha sınıfa ayrılmış gerektiğini önermiyoruz.

Carl "filizlenmiş sınıfında, ekstre işlevsellik kamu olmak için bu nedenle uygun olan, kendi varoluş nedeni olduğunu ve bu nedenle test sadece bir değişiklik olmadan test edilebilir değil.", Tamamlandığında bir işlevselliğe önemini (o en varoluş sebebi- ness) onun varlık kamu uygunluğu için temel değildir. Işlevselliği uygulama müşterinin bağımsızlık maksimize ederken işlevselliği varlık kamu uygunluğu için temel sınıfın işlevselliği kullanılabilir olacak şekilde istemci maruz arayüzü minimize olduğunu. Eğer filizlenmiş sınıfa sadece bir yöntem hareket Tabii ki, o zaman kamu olmak zorundadır. Eğer bir yöntem daha fazla hareket varsa, ancak, sınıfının müşterinin başarılı kullanımı için gerekli olan kamu bu yöntemleri yapmak gerekir: kalkan bu kamu yöntemler çok daha az önemli istediğiniz hangi özel yöntemlerden bazıları daha uzun olabilir sizin istemcisi. (Herhangi bir durumda, ben bir yöntemin önemi gibi "varoluş sebebi," ibaresi aynı zamanda iyi tanımlanmış değildir, bu bir fan değilim.)

Carl önermek için alternatif bir yaklaşım büyümek için sistemi nasıl tasavvur büyük bağlıdır. O bin daha az birkaç sınıf büyüyecek olursa, o zaman bu kopyalanan kaynağı "kamu", "özel" olarak, tüm kayıp değiştirmek, yeni bir dizine kaynak kodu kopyalayın ve daha sonra yazmak için bir komut dosyası sahip düşünebilirsiniz sizin Kopyalanan kaynağına karşı testleri. Bu kodu kopyalayın için gereken zaman ama orijinal kaynağı henüz kopyalanan sürümünde tüm yöntemler denenebilir yapma kapsüllemeyi korunması yararına aşağı tarafı var.

Aşağıda bu amaçla kullanmak yazısıdır.

Selamlar,

Ed Kirwan

!/bin/bash

rm-rf kodu kopya

kod kopyasını oluşturma yankı ...

mkdir kodu kopya

cp-r .. / www kodu kopya /

find code-copy -name "*php" -follow i için; do

sed -i 's/private/public/g' $i

tamam

php run_tests.php

Ben sadece mock nesneler tasarım sürücü icar harika bir yazı okudum:

http://www.mockobjects.com/files/usingmocksandtests.pdf

Carl "O işlevselliği ile bir sınıf filiz gerekir" dediği zaman sen 1) endişelenmenize gerek kalmaz, bu makalenin yazarı sizin testleri sizin sınıf tasarımı nasıl sahte nesnelerin kullanımı yoluyla, size rehberlik nasıl açıklayacağız hakkında özel parçaları test etmek mümkün olmayan, ve daha da önemlisi 2) Bu ederek tasarım artıracak nasıl (ben Carl'ın teklifi tefsir edeceğiz) sağ sorumluluğu ile işbirlikçileri ve rolleri keşfetmek.

Yazar, onun nokta çok net yapmak için adım adım bir örnek size alır.

İşte aynı yaklaşımı ile başka bir makale:

http://www.methodsandtools.com/archive/archive.php?id=90

Bir alıntı:

Many who start with TDD struggle with getting a grip on dependencies. To test an object, you exercise some behaviour and then verify whether an object is in an expected state. Because OO design focuses on behaviour, the state of an object is usually hidden (encapsulated). To be able to verify if an object behaves like expected, you sometimes need to access the internal state and introduce special methods to expose this state, like a getter method or a property that retrieves the internal state.

Apart from not wanting objects cluttering their interfaces and exposing their private parts, we neither want to introduce unnecessary dependencies with such extra getters. Our tests will become too tightly coupled and focused on implementation details.

A group of agile software development pioneers from the United Kingdom were also struggling with this back in 1999. They had to add additional getter methods to validate the state of objects. Their manager didn't like all this breaking of encapsulation and declared: I want no getters in the code! (Mackinnon et al., 2000 & Freeman et al., 2004)

The team came up with the idea to focus on interactions rather than state. They created a special object to replace the collaborators of objects under test. These special objects contained specifications for expected method calls. They called these objects mock objects, or mocks for short. The original ideas have been refined, resulting in several mock object frameworks for all common programming languages: Java (jMock, EasyMock, Mockito), .NET (NMock, RhinoMocks), Python (PythonMock, Mock.py, Ruby (Mocha, RSpec), C++ (mockpp, amop). See www.mockobjects.com for more information and links.