Büyük bir dosyayı yeniden düzenlemeyi ele almanın en iyi yolu nedir?


41

Şu anda ne yazık ki, her zaman takip edilmeyen yazılım kalitesi kurallarının bulunduğu bazı dosyalara sahip daha büyük bir proje üzerinde çalışıyorum. Bu, açıkça çok sayıda farklı işlevsellik içeren büyük dosyaları (2000-4000 satırları okuyun) içerir.

Şimdi bu büyük dosyaları yeniden küçük dosyalara dönüştürmek istiyorum. Mesele şu ki, çok büyük olduklarından, farklı dallardaki birden fazla kişi (ben dahil) bu dosyalar üzerinde çalışıyor. Bu yüzden, gelişmekte ve refraktörden gerçekten dallanamıyorum, çünkü bu refraktörleri diğer insanların değişiklikleriyle birleştirmek zorlaşacak.

Elbette herkesin dosyaları geliştirmek, yeniden "dondurmak" (örneğin, artık kimsenin düzenlemesine izin vermemek), refactor ve sonra "unfreeze" işlemlerini gerçekleştirmesini talep edebiliriz. Ancak bu da pek iyi değil, çünkü bu, yeniden yapılandırma işlemi yapılıncaya kadar herkesin temel olarak bu dosyalar üzerinde çalışmalarını durdurmasını gerektirecektir.

Öyleyse refactor yapmanın, başkasının çalışmayı bırakmasını (uzun süre) veya özellik dallarını geliştirmek için geri birleştirmelerini istemiyor musunuz?


6
Bunun da kullanılan programlama diline bağlı olduğunu düşünüyorum.
Robert Andrzejuk

8
"Küçük artımlı" checkinleri severim. Birisi repo kopyasını taze tutmadığı sürece, bu uygulama herkes için birleştirme çatışmalarını en aza indirecektir.
Matt Raffel

5
Testlerin neye benziyor? Yeniden düzenlemek için büyük bir (ve muhtemelen önemli!) Bir kod parçasını tercih edecekseniz, yeniden düzenleme işleminden önce test takımınızın gerçekten iyi durumda olduğundan emin olun. Bu, daha küçük dosyalarda doğru yaptığınızdan emin olmanızı çok daha kolay hale getirecektir.
corsiKa

1
Bununla başarabileceğiniz çok sayıda yaklaşım var ve en iyi yaklaşım sizin durumunuza bağlı olacaktır.
Stephen

3
En büyük dosyanın 10k satır uzunluğunda olduğu ve diğerleri arasında 6k satır uzunluğundaki ve herkesin dokunmaktan korktuğu bir sınıfı içeren projeye katıldım. Demek istediğim, sorunuzun harika olduğu. Farelerimizdeki kaydırma tekerleğinin kilidini açmak için bu tek sınıfın iyi bir neden olduğunu bir şaka bile icat ettik.
ElmoVanKielmo

Yanıtlar:


41

Bunun sosyal bir sorun kadar teknik olmadığını doğru bir şekilde anladınız: aşırı birleştirme çatışmalarından kaçınmak istiyorsanız, ekibin bu çatışmaları önleyecek şekilde işbirliği yapması gerekiyor.

Bu, Git ile ilgili daha büyük bir sorunun bir parçasıdır, bu dallanma çok kolaydır, ancak birleşme hala çok çaba gerektirebilir. Geliştirme ekipleri çok sayıda şube açmaya meyillidir ve daha sonra muhtemelen birleştirilmesinin zor olduğunu, muhtemelen bağlamını anlamadan Git Akışını taklit etmeye çalıştıkları için şaşırırlar.

Hızlı ve kolay birleşmelerin genel kuralı, büyüklükteki farklılıkların birikmesini önlemektir, özellikle dalların çok kısa ömürlü olması gerekir (saat veya gün, ay değil). Değişikliklerini hızlı bir şekilde entegre edebilen bir geliştirme ekibi daha az birleştirme çatışmaları görecektir. Bazı kodlar henüz üretime hazır değilse, onu entegre etmek ancak bir özellik bayrağıyla devre dışı bırakmak mümkün olabilir. Kod ana şubenize entegre edilir edilmez, yapmaya çalıştığınız yeniden düzenleme türüne erişilebilir olur.

Acil probleminiz için bu çok fazla olabilir. Ancak meslektaşlarınızdan bu dosyayı etkileyen değişiklikleri hafta sonuna kadar birleştirmelerini istemek mümkün olabilir, böylece yeniden düzenlemeyi gerçekleştirebilirsiniz. Daha fazla beklerlerse, birleşme çatışmalarının kendileri ile uğraşmak zorunda kalacaklar. Bu imkansız değil, sadece önlenebilir bir iş.

Ayrıca, büyük bağımlı kod parçalarını kırmayı önlemek ve yalnızca API uyumlu değişiklikler yapmak isteyebilirsiniz. Örneğin, bazı işlevleri ayrı bir modüle çıkarmak istiyorsanız:

  1. İşlevselliği ayrı bir modüle çıkartın.
  2. Çağrıları yeni API'ye iletmek için eski işlevleri değiştirin.
  3. Zamanla, yeni API'ye bağlantı noktasına bağlı kod.
  4. Son olarak, eski fonksiyonları silebilirsiniz.
  5. (Bir sonraki fonksiyonellik grubu için tekrarlayın)

Bu çok adımlı işlem birçok birleştirme çakışmasını önleyebilir. Özellikle, yalnızca çıkardığınız işlevselliği başka biri de değiştiriyorsa çatışmalar olacaktır. Bu yaklaşımın maliyeti, her şeyi bir seferde değiştirmekten çok daha yavaş olması ve geçici olarak iki yinelenen API'niz olması. Acil bir şey bu yeniden ateşlemeyi kesene kadar, bu kadar kötü değil, çoğaltma unutulmuş ya da depremitize ve bir demet teknoloji borcu ile sona erecek.

Ancak sonuçta, herhangi bir çözüm ekibinizle koordineli bir şekilde çalışmanızı gerektirecektir.


1
@Laiv Maalesef bu son derece genel bir öneri, ancak Sürekli Entegrasyon gibi çevik alandan çıkan bazı fikirlerin açıkça yararları var. Beraber çalışan takımlar (ve çalışmalarını sık sık bütünleştiren), yalnızca birbirleriyle çalışan takımlardan daha büyük çapraz değişiklikler yapmak için daha kolay bir zamana sahip olacaklar. Bu zorunlu olarak SDLC ile ilgili değil, ekip içindeki işbirliği ile ilgili değil. Bazı yaklaşımlar birlikte çalışmayı daha mümkün kılar (Açık / Kapalı Prensibi, mikro hizmetleri düşünün) ancak OP'nin ekibi henüz orada değil.
amon

22
Bir özellik dalının kısa bir ömre sahip olması gerektiğini söyleyecek kadar ileri gitmem - yalnızca ana dalından uzun süre ayrılmaması gerekir. Ana daldan özellik dalına düzenli aralıklarla yapılan değişiklikler, özellik dalının daha uzun süre kalması gereken durumlarda çalışır. Yine de, özellik dallarını gereğinden fazla tutmamak iyi bir fikirdir.
Dan Lyons,

1
@Laiv Tecrübelerime göre, bir yeniden düzenleme sonrası tasarımı ekiple önceden tartışmak mantıklı geliyor, ancak genellikle tek bir kişi kodda değişiklik yaparsa en kolay yoldur. Aksi takdirde, birleştirmek zorunda olduğunuz soruna geri dönersiniz. 4k çizgileri kulağa çok benziyor, ancak bu gerçekten extract sınıfı gibi hedeflenen yeniden yapılanmalar için değil . (Okudum olsaydı. Çok zor burada Martin Fowler Refactoring kitap Shill ediyorum) Ama 4k hatları olan yalnızca çok hedefsiz “adlı bu nasıl geliştirebileceğimizi görelim” gibi refactorings.
amon

1
@DanLyons Prensipte haklısınız: bu birleşme çabasının bir kısmını yayabilir. Uygulamada, Git'in birleşmesi , birleştirilen şubelerin en son ortak atalarına bağlıdır . Master → özelliğinin birleştirilmesi, master'da bize yeni bir ortak ata kazandırmaz, ancak master özelliği bir araya getirir. Tekrarlanan ana → özellik birleşmeleriyle, aynı çatışmaları tekrar tekrar çözmemiz gerekebilir (ancak bunu otomatikleştirmek için tekrar çalışın). Burada yeniden yapılanma kesinlikle üstündür çünkü ustanın ucu yeni ortak ata haline gelir, ancak tarih yazmanın başka sorunları da vardır.
öğleden

1
Cevap, git ve dallanmayı kolaylaştıracak aylaklar dışında benim için sorun yok ve bu nedenle çok sık dallar. Dallanma zor (veya en azından zahmetli) olduğunda, insanların tüm ilgili problemlerde, mümkünse genellikle kaçınmaları için yeterince SVN ve hatta CVS zamanlarını hatırlıyorum. Git'te, dağıtılmış bir sistem olarak, pek çok şubeye sahip olmak, aslında pek çok ayrı havuza sahip olmaktan farklı değildir (yani her bir dev üzerinde). Çözüm, başka yerlerde yatmaktadır, şubeye başvurmak kolay değildir. (Ve evet, görüyorum ki bu bir kenara ... ama yine de).
Saat

30

Yeniden düzenlemeyi daha küçük adımlarla yapın. Diyelim ki büyük dosyanızın adı var Foo:

  1. Yeni bir boş dosya ekleyin Barve "trunk" olarak kabul edin.

  2. FooÜzerine taşınabilecek kodun küçük bir bölümünü bulun Bar. Taşıma işlemini uygulayın, bagajdan güncelleyin, kodu oluşturun ve test edin ve "bagaja" bağlı kalın.

  3. 2. adımı tekrarlayın kadar Foove Bareşit büyüklüğe sahip (veya tercih boyutu ne olursa olsun)

Bu şekilde, ekip arkadaşlarınız dallarını bagajdan güncellediklerinde, değişikliklerinizi "küçük porsiyonlarda" alırlar ve tek tek birleştirebilirler; bu, tek bir adımda tam bir bölünmeyi birleştirmek zorunda kalmaktan çok daha kolaydır. Aynı şey, 2. adımda bir birleştirme çatışması olduğunda da geçerlidir, çünkü aralarında başka birisinin bagajını güncelledi.

Bu, birleştirme çakışmalarını veya manuel olarak çözülme gereksinimini ortadan kaldırmaz, ancak her çatışmayı daha yönetilebilir olan küçük bir kod alanıyla sınırlar.

Ve elbette - takımdaki yenilemeyi iletin. Arkadaşlarınıza ne yaptığınızı söyleyin, böylece belirli bir dosya için neden birleştirme çakışmaları beklemek zorunda olduklarını bilirler.


2
Bu, özellikle rerereseçenek seçeneklerinin etkin olması ile kullanışlıdır
D. Ben Knoble

@ D.BenKnoble: Bu ekleme için teşekkürler. İtiraf etmeliyim ki bir git uzmanı değilim (ama açıklanan sorun spesifik olarak git için değil, dallanmaya izin veren herhangi bir VCS için geçerlidir ve cevabım bu sistemlerin çoğuna uymalıdır).
Doktor Brown

Terminolojiye dayanarak düşündüm; Aslında, git ile, bu tür bir birleştirme hala sadece bir kez yapılır (eğer sadece biri çekip birleşirse). Ancak, kişi her zaman kendi tercihlerini çekip vişne-toplayabilir veya birleştirebilir veya dev'in tercihine bağlı olarak yeniden yapılandırabilir. Daha fazla zaman alır ancak otomatik birleştirme işleminin başarısız olması muhtemel görünüyorsa kesinlikle yapılabilir.
D. Ben Knoble

18

Dosyayı atomik bir işlem olarak bölmeyi düşünüyorsunuz, ancak yapabileceğiniz ara değişiklikler var. Dosya zamanla yavaş yavaş büyük oldu, zamanla yavaş yavaş küçük olabilir.

Uzun zamandır değişmeyecek bir parça seçin ( git blamebu konuda yardımcı olabilir) ve ilk önce ayırın . Bu değişikliği herkesin dallarıyla birleştirin, sonra ayrılacak en kolay kısmı seçin. Belki bir parçayı bölmek bile çok büyük bir adımdır ve önce büyük dosyada yeniden düzenleme yapmanız gerekir.

İnsanlar gelişmek için sık sık tekrar bir araya gelmiyorlarsa, teşvik etmelisiniz, sonra birleştikten sonra, değiştirdikleri parçaları ayırmak için bu fırsatı kullanın. Veya ayırma işlemini, istek çekme incelemesinin bir parçası olarak yapmalarını isteyin.

Fikir yavaş yavaş hedefinize doğru hareket etmektir. İlerlemenin yavaş olduğu hissine kapılacaksınız, ancak aniden kodunuzun çok daha iyi olduğunu fark edeceksiniz. Okyanus gemisini açmak çok uzun sürüyor.


Dosya büyük başlamış olabilir. Bu boyutta dosyalar hızlı bir şekilde oluşturulabilir. Bir günde veya haftada 1000'den fazla LoC yazabilen insanları tanıyorum. Ve OP, otomatik testlerden bahsetmedi, bu da eksik olduklarını gösteriyor.
ChuckCottrill

9

Bu soruna normalden farklı bir çözüm önereceğim.

Bunu bir takım kodu etkinliği olarak kullanın. Herkesin kodunu kontrol edebilecek kodlarını kontrol ettirin, daha sonra hala dosyada çalışan başkalarına yardım ettirin. İlgili herkes kodunu kontrol ettikten sonra, projektörü olan bir konferans salonu bulun ve bir şeyleri etrafta ve yeni dosyalara taşımaya başlamak için birlikte çalışın.

Buna belirli bir süre ayarlamak isteyebilirsiniz, böylece sonuçta görüşünüzü sonlandırmayan bir hafta boyunca tartışmaya değmez. Bunun yerine, her şey olması gerektiği gibi görünen şeyleri bulana kadar, haftada 1-2 saatlik bir etkinlik bile olabilir. Belki de dosyayı yeniden gözden geçirmek için sadece 1-2 saat gerekir. Muhtemelen deneyene kadar bilemezsin.

Bu, refactoring ile aynı sayfada bulunan herkesin yararınadır (punta amaçlanmamıştır), ancak gerektiğinde korumak için olası yöntem gruplandırmaları hakkında başkalarından girdi almanın yanı sıra, hataları önlemenize de yardımcı olabilir.

Bu şekilde yapmak, böyle bir şey yaparsanız, yerleşik bir kod incelemesine sahip olarak kabul edilebilir. Bu, uygun miktardaki geliştiricinin, kodunuzu teslim aldığınızda ve incelemeleri için hazır bulduğunuz anda imzalamasını sağlar. Yine de kaçırdığınız herhangi bir şey için kodu kontrol etmelerini isteyebilirsiniz, ancak inceleme işleminin daha kısa olmasını sağlamak için uzun bir yol gerekir.

Bu, işin kolayca gerçekleşmesini sağlayacak şekilde dağıtılmadığından, tüm durumlarda, ekiplerde veya şirketlerde çalışmayabilir. Ayrıca (yanlış) dev zamanın yanlış kullanımı olarak da yorumlanabilir. Bu grup kodu yöneticiden ve yeniden düzenleyicinin kendisinden katılım gerektirir.

Bu fikri yöneticinize satmanıza yardımcı olmak için, kod inceleme bitinden ve işin baştan nerede olduğunu bilen herkesden bahsedin. Dev'lerin zaman kaybettiklerini önlemek, bir dizi yeni dosyayı ararken kaçınmaya değer olabilir. Ayrıca, devlerin işlerin bitip bitmediği ya da "tamamen eksik" olduğu hakkında PO'ların önlenmesi genellikle iyi bir şeydir. (Eriyik ne kadar az olursa, IMO da o kadar iyi olur.)

Bir dosyayı bu şekilde yeniden ele geçirdikten sonra, başarılı ve yararlı olsaydı, daha fazla sayıda refaktör için daha kolay onay alabilirsiniz.

Yine de refactor'unuzu yapmaya karar veriyorsunuz, iyi şanslar!


Bu, çalışması için kritik olacak takım koordinasyonunu sağlamak için gerçekten iyi bir yol yakalayan harika bir öneri. Ek olarak, şubelerden bazıları masterilk önce birleştirilemezse , en azından odadaki herkesi bu şubelerdeki birleşme ile ilgilenmeye yardımcı olacaksınız.
Colin Young,

Mob kodunu önerdiğin için +1
Jon Raynor

1
Bu tam olarak sorunun sosyal yönünü ele almaktadır.
ChuckCottrill

4

Bu sorunu çözmek, diğer ekiplerden katılım gerektirir çünkü paylaşılan bir kaynağı (kodun kendisi) değiştirmeye çalışıyorsunuzdur. Söyleniyor, insanları rahatsız etmeden büyük monolitik dosyalara sahip olmanın "uzaklaşmasının" bir yolu olduğunu düşünüyorum.

Tek tek dosyaların boyutlarına ek olarak, büyük dosyaların sayısı kontrol edilemez bir şekilde artmadıkça, tüm büyük dosyaları bir kerede hedeflememeyi de tavsiye ederim .

Bu gibi büyük dosyaların yeniden düzenlenmesi genellikle beklenmeyen sorunlara neden olur. İlk adım, büyük dosyaların o anda ana veya geliştirme dallarında bulunanların ötesinde ek işlevler toplamasını engellemektir .

Bunu yapmanın en iyi yolunun varsayılan olarak büyük dosyalara belirli eklemeleri engelleyen taahhüt kancaları ile olduğunu düşünüyorum, ancak işlem mesajında ​​olduğu gibi sihirli bir yorumla reddedilebilir @bigfileok. Politikayı acısız ama izlenebilir bir şekilde geçersiz kılmak çok önemlidir. İdeal olarak, işleme kancasını yerel olarak çalıştırabilmeniz ve hata mesajının kendisinde bu belirli hatayı nasıl geçersiz kılacağınız anlatılmalıdır . Ayrıca, bu sadece benim tercihimdir, ancak kabul edilmeyen büyülü yorumlar veya taahhüt mesajında gerçekten ateşlemeyen hataları baskılayan büyülü yorumlar , bir tevdi zamanı uyarısı veya hatası olmalıdır; ihtiyaçları olsun olmasın.

Taahhüt kancası yeni sınıfları kontrol edebilir veya başka statik analizler yapabilir (geçici veya değil). Ayrıca, şu anki dosyadan% 10 daha büyük bir satır veya karakter sayısı seçebilir ve büyük dosyanın yeni sınırın ötesinde büyüyemeyeceğini söyleyebilirsiniz. Ayrıca, büyük dosyayı büyüten bireysel işleri çok fazla satır veya çok fazla karakter veya w / e reddedebilirsiniz.

Büyük dosya yeni işlevsellik biriktirmeyi bıraktığında, bir defada bir şeyleri yeniden değerlendirebilir (ve yeniden oluşturulmasını engellemek için aynı zamanda sabitleme kancalarının uyguladığı eşikleri azaltabilirsiniz).

Sonunda, büyük dosyalar, işleme kancalarının tamamen çıkarılabileceği kadar küçük olacaktır.


-3

Toplantı saatine kadar bekleyin. Dosyayı bölün, kesin ve usta birleştirmek.

Diğer insanlar da değişiklikleri, sabah saatlerinde diğer dallardaki gibi özellik dallarına çekmek zorunda kalacaklar.


3
Yine de, yeniden yapılanmalarımı değişiklikleriyle birleştirmek zorunda kalacakları anlamına gelirdi ...
Hoff


1
Aslında, eğer bu dosyaları değiştiriyorlarsa, yine de birleştirme ile uğraşmak zorundalar.
Laiv,

9
Bunun “Sürpriz, bütün eşyalarını kırdım” sorunu var. OP'nin bunu yapmadan önce katılım ve onay alması ve belli bir zamanda "devam etmekte olan" dosyasının kimsenin yardım edemeyeceği bir zamanda yapılması gerekiyor.
computercarguy

6
Çünkü Cthulhu aşkı bunu yapma. Takımda çalışmanın en kötü yolu bu.
Monica
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.