Kodumdaki derin girintileri önlemek için hangi adımları ve önlemleri alabilirim?
Kodumdaki derin girintileri önlemek için hangi adımları ve önlemleri alabilirim?
Yanıtlar:
Programınızdaki her işlev / yöntem bir ve sadece bir şey yaparsa , derin girinti genellikle bir sorun oluşturmaz. Bazen, koşulluları birkaç seviye derinliğe yerleştirmek gerekebilir , ama dürüstçe söyleyebilirim ki 12+ yıllık kodlamada sadece birkaç kez girintili kod yazdım.
Yapabileceğiniz en iyi şey özüt yöntemidir:
int Step1(int state)
{
if (state == 100)
{
return Step2(state);
}
else
{
return Step3(state);
}
}
int Step2(int state)
{
if (state != 100)
{
throw new InvalidStateException(2, state);
}
// ....
}
if
. Uç noktaya geldiğinde, çalıştırılabilir sözde kodla sonuçlanacaksın.
else
blokları düşürmektir .
Belki nöbet maddelerini düşünebilirsiniz ?
onun yerine
public void DoSomething(int value){
if (someCondition){
if(someOtherCondition){
if(yetAnotherCondition){
//Finally execute some code
}
}
}
}
Yapmak
public void DoSomething(int value){
if(!(someCondition && someOtherCondition && yetAnotherCondition)){
return;
//Maybe throw exception if all preconditions must be true
}
//All preconditions are safe execute code
}
Eğer bir şansınız varsa Steve McConnell'in Code Complete'i okumanızı tavsiye ederim. Bu konularda çok büyük tavsiyeleri var.
http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6
"Muhafız hükümleri" hakkında daha fazla bilgi için bakınız: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses
Anahtar kelimelerinizi ters çevirin if
.
Onun yerine:
if (foo != null)
{
something;
something;
if (x)
{
something;
}
something;
}
else
{
boohoo;
}
Yazarım:
if (foo == null)
{
boohoo;
return;
}
something;
something;
if (x)
{
something;
}
something;
Aynısı if
- else
blokları için de geçerlidir . Daha else
kısa / daha az iç içe ise, geri alın.
Parametrelerin değerlerini tek bir yerde kontrol edin
Metodunuzu girer girmez tüm parametreleri geçersiz değerler için kontrol edin, ardından güvenli olduğunuzu bilmeye devam edin. Daha okunabilir kod sağlar, ancak daha sonra koşullu blokları biriktirmenizi ve bu kontrolleri altyordamın her tarafına yaymanızı sağlar.
If
kodun başlangıcında bazı koşulların yerine getirilmemesi nedeniyle yürütme akışını durduran kodlar @ @ JasonTuran'ın işaret ettiği gibi koruma maddeleri olarak da bilinir . Ve bu, farklı bir isme sahip olmak kadar yakın görünüyor.
Genellikle, derin girintili kod genellikle sorunlu kod olduğunu gördüm. Bu sorunla karşı karşıyaysanız, geri adım atın ve işlevinizin çok fazla şey yapıp yapmadığını değerlendirin.
Aynı zamanda, sorunuzu cevaplamak için, o kadar derinden girintiye ihtiyaç varsa, orada olmasına izin vermenizi öneririm. Basit bir nedenle, bu kodda girinti çok uzun bir kod parçası olacağından yardımcı olacaktır.
Yuvalanmış bileşenleri (özellikle tekrarlananları) ayrı işlevlere ayırın (diliniz kapanmaları destekliyorsa bu daha kolaydır) veya bir dizi iç içe döngüyü özyineleme ile değiştirin.
Ayrıca, dört yerine iki boşluk girin.
Derin girintileri kaldırılacak kategorik bir sorun olarak görmüyorum (ne de yeniden düzenlemeyi her şeyin gerçek cevabı olarak görmüyorum).
Genellikle iç içe ifs yerine, mantıksal ifadeler yazmak istiyorum:
if (foo && bar && baz)
ziyade
if foo
if bar
if baz
Kendime inanmadım, ancak Code Complete'e göre burası kullanmak için uygun bir yer break
(eğer ekibiniz gemideyse). Bu sadece bir döngü yazmak gibi hissetmiyorum zaman kullanılan Delphi programcılar ile olduğu gibi ifadelerde break
kullanılan olsa da, C ++ programcıları ile daha kabul edilebilir olduğunu hayal ediyorum .switch
break
while
Girinti gerçekten savaşmayı düşünüyor. Yapmayı öğrendiğim şey, önce yöntemi parçalara bölmek, sonra bir parça başarısız olursa aşağıdaki her parçayı atlamak için garip bir numara kullanmaktır. İşte bir örnek :
Onun yerine :
{if (networkCardIsOn() == true)
{if (PingToServer() == true)
{if (AccesLogin(login,pass) == true)
{if (nextCondition == true)
...
}
}
}
Şu anda yazıyorum:
{vbContinue = true;
if (vbContinue) {
vbContinue = networkCardIsOn();
if (vbContinue == false) {
code to Handle This Error();
}
}
if (vbContinue) {
vbContinue = PingToServer();
if (vbContinue == false) {
code to HandleThisError2();
}
}
if (vbContinue) {
vbContinue = AccesLogin(login,pass);
if (vbContinue == false) {
HandleThisErrorToo();
}
}
...
Bu ilk başta bana garip geldi, ama bunu kullandığımdan beri bakım maliyeti yarıya bölündü ve beynim günün sonunda daha havalı.
Aslında, bu "teknik" ile elde edilen kazanç, kod karmaşıklığının gerçekten bölünmesidir, çünkü kod daha az yoğundur.
Kodu okurken, geçmiş koşullar hakkında hiçbir şey hatırlamanız gerekmez: Kodun o noktasındaysanız, önceki adımlar atılmış ve başarılı olmuştur.
Diğer bir kazanç ise "if-else" ile iç içe olan tüm bu "kaçış yolu ve koşulu" nun basitleştirilmesidir.