Çoğunlukla bir regex içeren büyük işlevleri yeniden düzenlemeli miyim? [kapalı]


15

Az önce yaklaşık 100 satırlık bir fonksiyon yazdım. Bunu duyduğunda, muhtemelen bana tek sorumlulukları anlatmak ve beni refactor'a çağırmak için cazipsin. Benim içgüdüm de bu, ama işte sorun: İşlev bir şey yapar . Karmaşık bir dize manipülasyonu gerçekleştirir ve işlev gövdesi çoğunlukla belgelenmiş birçok satıra bölünmüş bir ayrıntılı regex'ten oluşur. Normal ifadeyi birden fazla işleve ayırırsam, dilleri etkili bir şekilde değiştirdiğim ve normal ifadelerin sunduğu bazı özelliklerden yararlanamayacağım için aslında okunabilirliği kaybedeceğimi hissediyorum . İşte sorum şu:

Düzenli ifadelerle dize manipülasyonu söz konusu olduğunda, büyük fonksiyon gövdeleri hala bir anti-desen midir? Adlandırılmış yakalama grupları işlevlere çok benzer bir amaca hizmet ediyor gibi görünüyor. Bu arada, normalden geçen her akış için testlerim var.


3
Büyük bir kısmının dokümantasyon olduğunu düşünürseniz, işlevinizde bir sorun olduğunu düşünmüyorum . Bununla birlikte, ilk etapta büyük bir düzenli ifade kullanmakla ilgili bir sürdürülebilirlik sorunu olabilir.
Joel Cornett

2
Sorununuza en iyi çözümün dev bir regex olduğundan emin misiniz? Ayrıştırıcı kitaplığı veya özel dosya biçimini standart bir formatla (XML, JSON vb.) Değiştirme gibi daha basit alternatifler düşündünüz mü?
lortabac

2
Bu normal ifadenin değiştirilmiş / geliştirilmiş / basitleştirilmiş bir sürümünü kullanan başka işlevler var mı? Bu, yeniden düzenlemenin gerçekleşmesi gereken önemli bir gösterge olacaktır. Değilse, ben de olduğu gibi bırakırım. Bunun gibi karmaşık bir dize manipülasyonuna ihtiyaç duymak kendi başına sarı bir bayraktır (bağlamı bilmiyorum, dolayısıyla sadece sarı) ve işlevi yeniden düzenlemek bana daha çok kişinin hissettiği suçluluktan kurtulmak için bir ritüel gibi görünüyor it;)
Konrad Morawski

8
100 satırlık normal ifade nasıl sadece 1 şey yapabilir?
Pieter B

@lortabac: Giriş kullanıcı tarafından oluşturulan metindir (düzyazı)
DudeOnRock

Yanıtlar:


36

Karşılaştığınız şey, mantıklı karar verme süreci üzerine "en iyi uygulamalar" kisvesi altında kurallara köleli bir şekilde bağlı kalmayı tercih eden insanları dinlemekten kaynaklanan bilişsel uyumsuzluktur.

Ödevinizi açıkça yaptınız:

  • Fonksiyonun amacı anlaşılır.
  • Uygulamasının çalışmaları anlaşılır (yani okunabilir).
  • Uygulamanın tam kapsamlı testleri vardır.
  • Bu testler geçer, yani uygulamanın doğru olduğuna inanırsınız.

Bu noktalardan herhangi biri doğru olmasaydı, işlevinizin çalışması gerektiğini söyleyen ilk kişi olurdum. Yani kodu olduğu gibi bırakmak için bir oy var.

İkinci oylama seçeneklerinize ve her birinden ne aldığınız (ve ne kaybettiğiniz) bakmaktan gelir:

  • Elden Geçirme.Bu, birisinin bir fonksiyonun ne kadar olması gerektiği fikrine uymanızı sağlar ve okunabilirliği feda eder.
  • Hiçbir şey yapma. Bu, mevcut okunabilirliği korur ve birinin bir işlevin ne kadar sürmesi gerektiği fikrine uymayı feda eder.

Daha fazla değer verdiğiniz bu karar verilir: okunabilirlik veya uzunluk. Uzunluğun güzel olduğuna inanılan ama okunabilirliğin önemli olduğuna inanan kampa düşüyorum ve ikincisini haftanın her günü eski haline getireceğim.

Alt satır: kırık değilse, tamir etmeyin.


10
+1 "Bozuk değilse düzeltmeyin."
Giorgio

Aslında. Sandy Metz kuralları ( gist.github.com/henrik/4509394 ) iyi ve hepsi, ancak youtube.com/watch?v=VO-NvnZfMA4#t=1379'da nasıl olduklarını ve insanların neden aldıklarını anlatıyor onları çok ciddiye alıyorlar.
Amadan

@Amdan: Videodaki ekstra bağlamla Metz'in yaptığı mantıklı. Bir müşteriye tavsiyesi, bir ucunda, diğer ucunda daha makul ortama sürüklemenin bir yolu olarak aşırı olan davranışa karşı aşırı derecede aşırıydı. Bu tartışmanın geri kalanı cevabımın itişine dayanıyor: inanç değil akıl yürütme, en iyi eylem yolunu belirlemenin yoludur.
Blrfl

19

Dürüst olmak gerekirse, işleviniz "bir şey yapabilir", ancak sizin belirttiğiniz gibi

Normal ifadeyi birden fazla işleve ayırmaya başlayabilirim,

Bu da reg ex kodunuzun birçok şeyi yaptığı anlamına gelir. Ve sanırım daha küçük, bireysel olarak test edilebilir birimlere bölünebilir. Ancak, bu iyi bir fikir ise, cevaplamak kolay değildir (özellikle gerçek kodu görmeden). Ve doğru cevap ne "evet" ne de "hayır" olabilir, ama "henüz değil, ama bir dahaki sefere bu reg exp'deki bir şeyi değiştirmek zorundasınız" olabilir.

ancak dilleri etkili bir şekilde değiştirdiğim için okunabilirliği gerçekten kaybedecekmiş gibi hissediyorum

Ve bu temel nokta - reg ex dilinde yazılmış bir kod parçanız var . Bu dil, kendi içinde soyutlama için iyi bir araç sağlamaz (ve "adlandırılmış yakalama grupları" işlevlerinin yerine geçmez). Bu yüzden "reg ex dilinde" yeniden düzenleme gerçekten mümkün değildir ve ana bilgisayar dili ile iç içe daha küçük reg exps gerçekten okunabilirliği artıramayabilir (en azından öyle hissediyorsunuz , ancak şüpheleriniz var, aksi takdirde sorunuzu yayınlamazsınız) . İşte benim tavsiyem

  • başkalarının sizin gibi okunabilirliği düşündüğünden emin olmak için kodunuzu başka bir gelişmiş geliştiriciye gösterebilirsiniz (belki /codereview// ). Başkalarının sizin gibi okunabilir bir 100 satır reg exp bulamayabileceği fikrine açık olun. Bazen "daha küçük parçalara kolayca kırılamaz" kavramı sadece ikinci bir gözle aşılabilir.

  • gerçek evrilebilirliği gözlemleyin - yeni gereksinimleriniz geldiğinde ve bunları uygulamak ve test etmek zorunda olduğunuzda parlak reg exp'niz hala çok iyi görünüyor mu? Reg exp çalıştığınız sürece, ona dokunmayacağım, ancak bir şeyin değiştirilmesi gerektiğinde, bu büyük bloğa everyhing koymanın gerçekten iyi bir fikir olup olmadığını tekrar düşünürdüm - ve (ciddi olarak!) daha küçük parçalar daha iyi bir seçenek olmazdı.

  • sürdürülebilirliği gözlemleyin - mevcut formdaki reg exp'yi etkili bir şekilde hata ayıklayabilir misiniz? Özellikle bir şeyi değiştirmek zorunda kaldıktan sonra, şimdi testleriniz size bir şeyin yanlış olduğunu söylüyorsa, temel nedeni bulmanıza yardımcı olan bir reg exp hata ayıklayıcı var mı? Hata ayıklama zorlaşırsa, bu da tasarımınızı yeniden değerlendirmek için bir fırsat olacaktır.


Adlı yakalama gruplarının (genel olarak yakalama gruplarının) son / bir kez yazma değişkenlerine veya belki de makrolara en çok benzediğini söyleyebilirim. Normal ifade işlemcisinden döndürülen eşleme nesnesinden veya daha sonra normal ifadenin kendisinde eşleşmenin belirli bölümlerine başvurmanıza izin verir.
JAB

4

Bazen bir şeyi yapan daha uzun bir işlev, bir iş birimini işlemenin en uygun yoludur. Bir veritabanını sorgulamaya başladığınızda (en sevdiğiniz sorgu dilini kullanarak) kolayca çok uzun işlevlere girebilirsiniz. Bir işlevi (veya yöntemi) belirtilen amacı ile sınırlandırırken daha okunabilir hale getirmek için, bir işlevin en çok arzu edilen sonucunu dikkate alacağım şeydir.

Kod boyutu söz konusu olduğunda uzunluk keyfi bir "standart" tır. C # 'da 100 satır fonksiyonunun uzunlamasına kabul edilebildiği durumlarda, montajın bazı versiyonlarında küçük olur. Bir rapor için çok karmaşık bir veri kümesi döndüren kod satır 200 satır içine bazı SQL sorguları gördük.

Tamamen çalışan kod , yani sen gibi basit gibidir makul o hedeftir olun.

Sadece uzun olduğu için değiştirmeyin.


3

Her zaman normal ifadeyi alt normal ifadelere bölebilir ve yavaş yavaş son ifadeyi oluşturabilirsiniz. Bu, özellikle aynı alt model birçok kez tekrarlanırsa, çok büyük bir modelin anlaşılmasına yardımcı olabilir. Örneğin Perl'de;

my $start_re = qr/(?:\w+\.\w+)/;
my $middle_re = qr/(?:DOG)|(?:CAT)/;
my $end_re = qr/ => \d+/;

my $final_re = $start_re . $middle_re . $end_re;
# or: 
# my $final_re = qr/${start_re}${middle_re}${end_re}/

Önerdiğinden bile daha uygun olan ayrıntılı bayrağı kullanıyorum.
DudeOnRock

1

Eğer kırılabilirse kır diyebilirim. sürdürülebilirlik açısından ve belki de yeniden dayanıklılık açısından onu kırmak mantıklıdır, ancak elbette işlevinizin doğallığını ve nasıl girdi elde ettiğinizi ve neye geri döneceğini düşünmelisiniz.

Parçalanmış veriyi nesnelere akış olarak ayrıştırmaya çalıştığımı hatırlıyorum, bu yüzden temelde yaptığım iki ana bölüme ayırdım, biri kodlanmış metinden tam bir String birimi oluşturuyordu ve ikinci bölümde bu birimleri veri sözlüğüne ayrıştırıp düzenledim (farklı nesne için rastgele özellik olabilir) ve nesneleri güncellemek veya oluşturmaktan daha fazlası.

Ayrıca her ana parçayı daha küçük ve daha özel fonksiyonlara ayırabilirim, bu yüzden sonunda her şeyi yapmak için 5 farklı fonksiyonum vardı ve bazı fonksiyonları farklı bir yerde tekrar kullanabilirim.


1

Düşündüğünüz veya düşünmediğiniz bir şey, o dilde normal ifade kullanmak yerine kullandığınız dilde küçük bir ayrıştırıcı yazmaktır. Bunu okumak, test etmek ve bakımını yapmak daha kolay olabilir.


Bunu kendim düşündüm. Sorun girdinin düz olması ve bağlam ve biçimlendirmeden ipuçları alıyorum. Böyle bir şey için bir ayrıştırıcı yazmak mümkünse, daha fazla bilgi edinmek isterim! Kendim bir şey bulamadım.
DudeOnRock

1
Bir normal ifade onu ayrıştırabilirse, ayrıştırabilirsiniz. Cevabınız bana ayrıştırma konusunda bilgili olamayacağınızı gösteriyor. Eğer durum buysa, normal ifadeye bağlı kalmak isteyebilirsiniz. Ya bu ya da yeni bir beceri öğren.
Thomas Eding

Yeni bir beceri öğrenmek isterim. Önerebileceğiniz iyi kaynaklar var mı? Bunun arkasındaki teori ile de ilgileniyorum.
DudeOnRock

1

Çoğu durumda dev regex'ler kötü bir seçimdir. Deneyimlerime göre, geliştirici ayrıştırmaya aşina olmadığından sıklıkla kullanılırlar (bkz. Thomas Eding'in cevabı ).

Her neyse, regex tabanlı bir çözüme bağlı kalmak istediğinizi varsayalım.

Gerçek kodu bilmediğim için, iki olası senaryoyu inceleyeceğim:

  • Normal ifade basittir (çok sayıda gerçek eşleme ve birkaç alternatif)

    Bu durumda, tek bir normal ifadeyle sunulan gelişmiş özellikler vazgeçilmez değildir. Bu, onu bölmekten muhtemelen yararlanacağınız anlamına gelir.

  • Normal ifade karmaşıktır (birçok alternatif)

    Bu durumda gerçekçi bir şekilde tam test kapsamına sahip olamazsınız, çünkü muhtemelen milyonlarca olası akışınız vardır. Bu nedenle, test etmek için bölmeniz gerekir.

Hayal gücümden yoksun olabilirim, ancak 100 satırlık regex'in iyi bir çözüm olduğu herhangi bir gerçek dünya durumu düşünemiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.