Özelleştirilmiş yazılımı nasıl düzenlersiniz?


28

Dünyadaki çeşitli müşteriler için özel olarak uyarlanmış büyük bir yazılım projesi üzerinde çalışıyorum. Bunun anlamı, çeşitli müşteriler arasında ortak olan% 80'lik bir koda sahip olduğumuz anlamına gelir, aynı zamanda bir müşteriden diğerine değişmesi gereken çok sayıda koda sahip olduğumuz anlamına gelir. Geçmişte gelişimimizi ayrı depolarda (SVN) yaptık ve yeni bir proje başladığında (az sayıda fakat büyük müşterimiz var), geçmiş projenin ihtiyaçlarımız için en iyi kod temeline sahip olmasına dayanarak başka bir depo oluşturduk. Bu geçmişte çalıştı, ancak birkaç sorunla karşılaştık:

  • Bir depoda sabitlenen hatalar diğer depolarda yamalı değildir. Bu bir organizasyon sorunu olabilir, ancak 5 depoda bir hatayı düzeltmeyi ve düzeltmeyi zor buluyorum, bu deposu sürdüren ekibin dünyanın başka bir yerinde olabileceğini ve onların test ortamına sahip olamayacağımızı aklımda tutuyorum. ne programlarını ne de ne istediklerini bilmiyorlar (bir ülkedeki "hata", başka bir ülkede "özellik" olabilir).
  • Bir proje için yapılan, başka bir proje için de yararlı olabilecek özellikler ve iyileştirmeler kaybedilir veya başka bir projede kullanılırlarsa, sık sık onları bir kod tabanından diğerine birleştiren büyük baş ağrısına neden olurlar (çünkü her iki dal da bir yıl boyunca bağımsız olarak geliştirilebilmektedir) ).
  • Bir geliştirme branşında yapılan yeniden yapılanmalar ve kod iyileştirmeleri , şubeler arasında tüm bu değişiklikleri birleştirmek zorunda kalırsanız ya kaybolur ya da daha fazla zarara neden olur.

Şimdi bu problemlerin nasıl çözüleceğini tartışıyoruz ve şimdiye kadar bunun nasıl çözüleceğine dair aşağıdaki fikirleri ortaya çıkardık:

  1. Ayrı branşlarda gelişmeyi sürdürün ancak genel hata düzeltmelerinin birleştirildiği merkezi bir depoya sahip ve tüm projelerin bu merkezi depodaki değişiklikleri düzenli olarak (örneğin günlük olarak) kendi başlarına birleştirmelerini sağlayarak daha iyi organize edin . Bu da büyük disiplin ve dallar arasında birleşme için çok çaba gerektirir. Bu yüzden işe yarayacağına ikna olmadım ve bu disiplini, özellikle zaman baskısı ortaya çıktığında tutabiliriz.

  2. Ayrı gelişim kollarını terk edin ve tüm kodlarımızın yaşadığı ve takılabilir modüller ve konfigürasyon seçenekleri kullanarak özelleştirmemizi sağlayan merkezi bir kod deposuna sahip olun. Kodumuzdaki bağımlılıkları çözmek için zaten Bağımlılık Enjeksiyonu konteynerlerini kullanıyoruz ve işletme mantığını kullanıcı arayüzümüzden temiz bir şekilde ayırmak için çoğu kodumuzdaki MVVM modelini takip ediyoruz.

İkinci yaklaşım daha zarif görünüyor, ancak bu yaklaşımda birçok çözülmemiş sorunumuz var. Örneğin: modelinizdeki / veritabanınızdaki değişiklikleri / eklemeleri nasıl ele alırsınız. Güçlü bir şekilde yazılmış varlıklara sahip olmak için .NET'i Entity Framework ile kullanıyoruz. Veri modelimizi karıştırmadan bir müşteri için gerekli olan ancak başka bir müşteri için yararsız olan özellikleri nasıl kullanabileceğimizi anlamıyorum. Bunu veritabanında çözmeyi düşünüyoruz (uyduları kullanarak (belirli bir varlık için fazladan sütunlarımızın 1: 1 ile eşlendiği orijinal varlık ile eşleştirilen ayrı bir tabloya sahip), ancak bu sadece veritabanı. Bunu kodda nasıl ele alıyorsunuz? Veri modelimiz, bu yaklaşımı kullanarak her bir müşteri için uzatamayacağımız merkezi bir kütüphanede yaşıyor.

Bu sorunla mücadele eden tek takım olmadığımızdan eminim ve konuyla ilgili çok az malzeme bulmaktan şok oluyorum.

Yani benim sorum şu:

  1. Son derece özelleştirilmiş yazılım konusunda ne gibi deneyimleriniz var, hangi yaklaşımı seçtiniz ve sizin için nasıl çalıştı?
  2. Hangi yaklaşımı öneriyorsunuz ve neden? Daha iyi bir yaklaşım var mı?
  3. Konuyla ilgili önerebileceğin iyi kitaplar veya makaleler var mı?
  4. Teknik ortamımız için özel önerileriniz var mı (.NET, Entity Framework, WPF, DI)?

Düzenle:

Tüm önerileriniz için teşekkürler. Fikirlerin çoğu, zaten ekibimizde sahip olduğumuz fikirlerle eşleşiyor, ancak onlarla birlikte edindiğiniz deneyimi ve bunları daha iyi uygulamak için ipuçlarını görmek gerçekten yararlı.

Hala hangi yöne gideceğimizden emin değilim ve karar vermiyorum (yalnız), ama bunu takımımda geçireceğim ve bunun yardımcı olacağından eminim.

Şu anda, tenor müşteriye özel modülleri kullanarak tek bir havuz gibi görünüyor. Mimarimizin buna bağlı olduğundan veya uygun hale getirmek için ne kadar yatırım yapmamız gerektiğinden emin değilim, bu nedenle bazı şeyler bir süre ayrı depolarda yaşayabilir, ancak işe yarayacak tek uzun çözüm olduğunu düşünüyorum.

Yani, tüm cevaplar için tekrar teşekkürler!


Veritabanı tablolarını kod olarak ele almayı düşünün.

Bunu zaten bizim yıkım havuzumuzdaki veritabanı komut dosyalarımız olduğu anlamında yapıyoruz, ancak yukarıda belirtilen sorunları çözmüyor. Veri tabanı modelimizde Anahtar Değer stil tabloları olmasını istemiyoruz çünkü birçok sorunla birlikte geliyorlar. Öyleyse, her biri için paylaşılan bir kod deposunu korurken, bireysel müşteriler için modelinize eklemelere nasıl izin veriyorsunuz?
aKzenT

Yanıtlar:


10

Temel problem, sadece kod deposu bakımı değil , uygun mimari eksikliğidir .

  1. Her zaman tüm sistemler tarafından paylaşılacak olan sistemin özü / özü nedir?
  2. Her müşteri için hangi iyileştirmeler / sapmalar gerekir?

Bir çerçeve ya da standart bir kütüphane eskisini kapsamaktadır, ikincisi ise eklentiler olarak uygulanacaktır (eklentiler, alt sınıflar, DI, kod yapısı için ne mantıklı olursa olsun).

Şubeleri yöneten ve dağıtımı geliştiren bir kaynak kontrol sistemi de muhtemelen yardımcı olacaktır; Mercurial hayranıyım, diğerleri Git'i tercih ediyor. Çerçeve ana dal, her özelleştirilmiş sistem örneğin alt dal olacaktır.

Sistemi uygulamak için kullanılan spesifik teknolojiler (.NET, WPF, her neyse) büyük ölçüde önemsizdir.

Bu hakkı almak kolay değil , ancak uzun vadeli uygulanabilirlik için kritik öneme sahip . Ve elbette, ne kadar beklerseniz, başa çıkmanız gereken teknik borç da o kadar büyük olur.

Yazılım Mimarisi: Organizasyonel Prensipler ve Kalıplar kitabını yararlı bulabilirsiniz.

İyi şanslar!


3
Evet. Mimarlık genellikle teknik bir şeyden çok psikolojik bir şeydir. Tamamen ürüne odaklanırsanız, bileşenlerin yalnızca o ürün için yararlı olduğu bir çalışma dökümü ile sonuçlanacak. Öte yandan, daha genel olarak yararlı olacak bir dizi kitaplık oluşturmaya odaklanırsanız, daha geniş bir durumda konuşlandırılabilecek bir dizi yetenek geliştirirsiniz. Anahtar, elbette, kendi durumunuz için bu iki uç nokta arasındaki doğru dengeyi bulmaktır.
William Payne

Şubelerimizin çoğu arasında (>% 90) büyük bir paylaşılan bölüm olduğunu düşünüyorum, ancak son% 10 her zaman farklı yerlerde, bu nedenle bazı yardımcı program kütüphaneleri dışında bazı müşteriye özel değişiklikleri hayal edemediğim çok az bileşen var. herhangi bir iş mantığı içermez.
aKzenT

@ aKzenT: hmmm ... hayal etme, onun yerine ölç. Kodu inceleyin ve özelleştirmenin gerçekleştiği tüm yerlere bakın, değiştirilen bileşenlerin bir listesini yapın, her bir bileşenin ne sıklıkta değiştirildiğini not alın ve yapılan değişikliklerin çeşitlerini ve kalıplarını düşünün. Kozmetikler mi yoksa algoritmik mi? Temel işlevsellik ekliyor mu yoksa değiştiriyorlar mı? Her bir değişimin sebebi nedir? Yine, bu zor bir iştir ve keşfettiğiniz şeylerin sonuçlarından hoşlanmayabilirsiniz.
Steven A. Lowe

1
Bunu cevap olarak kabul ettim, çünkü bu kararı, mimarimiz hakkında daha fazla düşünmeden önce, ortak olan kısımları mı yoksa ortak olması gerektiğini mi belirleyemeyiz ve sonra tek bir havuzla mı yaşayabileceğimizi veya çatallama gerekip gerekmediğini göremeyiz. en azından şu an). Bu cevap, bu en iyi IMO'yu yansıtıyor. Diğer tüm yazılar için teşekkürler!
aKzenT

11

Çalıştığım bir şirket aynı problemi yaşıyordu ve problemi çözme yaklaşımı şuydu: Tüm yeni projeler için ortak bir çerçeve oluşturuldu; Bu, her projede aynı olması gereken her şeyi içerir. Örneğin, form üreten araçlar, Excel'e dışa aktarma, günlük oluşturma Bu ortak çerçevenin sadece iyileştirilmesi (yeni bir proje yeni özelliklere ihtiyaç duyduğunda) fakat hiçbir zaman çatallanmadığı için çaba harcandı.

Bu çerçeveye dayanarak, müşteriye özel kod ayrı depolarda sağlandı. Yararlı veya gerekli olduğunda, hata düzeltmeleri ve iyileştirmeler projeler arasında kopyalanır (soruda açıklanan tüm uyarılarla birlikte). Bununla birlikte, küresel olarak yararlı gelişmeler ortak çerçeveye girmektedir.

Tüm müşteriler için ortak bir kod tabanında her şeyin bir takım avantajları vardır, ancak diğer taraftan, ifprogramın her müşteri için farklı davranmasını sağlamak için sayısız s olduğunda kodu okumak zorlaşır .

EDIT: Bunu daha anlaşılır kılmak için bir fıkra:

Bu şirketin alanı depo yönetimidir ve depo yönetim sisteminin bir görevi, gelen ürünler için boş bir depo yeri bulmaktır. Sesler kolay, ancak pratikte, birçok kısıtlama ve stratejinin gözlenmesi gerekir.

Bir noktada, yönetim bir programcıdan, çeşitli farklı stratejiler uygulayan ve sonraki tüm projelerde kullanılması gereken depolama yerlerini bulmak için esnek, parametrelendirilebilir bir modül yapmasını istedi. Asil çaba, anlaşılması ve bakımı çok zor olan karmaşık bir modülle sonuçlandı. Bir sonraki projede, proje lideri bu depoda nasıl çalışacağını çözemedi ve söz konusu modülün geliştiricisi gitti, bu yüzden sonunda onu görmezden geldi ve bu görev için özel bir algoritma yazdı.

Birkaç yıl sonra, bu modülün başlangıçta kullanıldığı deponun düzeni değişti ve tüm esnekliğine sahip modül yeni gereksinimlere uymadı; Ben de orada özel bir algoritma ile değiştirdim.

LOC'nin iyi bir ölçüm olmadığını biliyorum ama yine de: "esnek" modülün boyutu ~ 3000 LOC (PL / SQL) iken, aynı görev için özel bir modül ~ 100..250 LOC alır. Bu nedenle, esnek olmaya çalışmak, umduğumuz yeniden kullanılabilirliği kazanmadan, kod tabanının boyutunu oldukça arttırdı.


Geri bildiriminiz için teşekkürler. Bu tarif edilen ilk çözümün bir uzantısıdır ve biz de bunu düşündük. Ancak, kütüphanelerimizin çoğu bazı çekirdek varlıkları kullandığından ve bu çekirdek varlıklar genellikle bir müşteri ya da başka bir müşteri için genişletildiğinden, bu çekirdek depoya yalnızca çok az kitaplık koyabileceğimizi düşünüyorum. Örneğin, hemen hemen bütün diğer kütüphanelerimiz ve programlarımızın kullandığı bir kütüphanede tanımlı ve bir “Müşteri” varlığımız var. Ancak her müşterinin bir "Müşteriye" eklemesi gereken bazı ekstra alanları vardır, bu yüzden bu kütüphaneyi ve dolayısıyla tüm kütüphaneleri ona bağlı olarak kullanmamız gerekir.
aKzenT

3
Sayısız "ifs" den kaçınmak konusundaki fikrimiz, bağımlılık enjeksiyonunu kapsamlı bir şekilde kullanmak ve farklı müşteriler için komple modüller alışverişi yapmaktır. Bunun nasıl sonuçlanacağından emin değilim. Bu yaklaşım sizin için nasıl çalıştı?
aKzenT

+1, bu temelde bunu iyi idare eden projelerdeki deneyimlerime uyar. 'Farklı müşteriler için ifs' yaklaşımını kullanacaksanız, 2 puan: 1. Eğer (müşteri1) ... yapmayın, bunun yerine (configurationOption1) ... yapın ve müşteri başına yapılandırma seçeneklerine sahip olun. 2. Yapmamaya çalışın! Konfigürasyona özel modüllere sahip olmaktan daha iyi (daha anlaşılabilir / kolay bakım yapılabilir) seçenek olacak zamanın% 1'i belki de olabilir.
vaughandroid

@Baqueta: Sadece açıklığa kavuşturmak için: yapılandırma seçenekleri yerine müşteri başına modülleri kullanmanızı öneririz. Müşteriler yerine özellikleri birbirinden ayırt etme fikrinizi seviyorum. Bu yüzden her ikisinin kombinasyonu, yapılandırma seçenekleriyle kontrol edilen çeşitli "özellik modüllerine" sahip olmak olacaktır. Bir müşteri daha sonra sadece bir dizi bağımsız özellik modülü olarak temsil edilir. Bu yaklaşımı çok seviyorum, ama bunun nasıl tasarlanacağından emin değilim. DI modül yükleme ve değiştirme problemini çözüyor, ancak müşteriler arasında farklı veri modellerini nasıl yönetiyorsunuz?
aKzenT

Evet, özellik başına modüller ve ardından müşteri başına yapılandırma / özellik seçimi. DI ideal olur. Ne yazık ki, önemli müşteri başına kişiselleştirme gereksinimlerinizi hiçbir zaman tek bir veri kitaplığıyla birleştirmek zorunda kalmamıştım, bu yüzden orada çok fazla yardımcı olabileceğimden emin değilim ...
vaughandroid

5

Üzerinde çalıştığım projelerden biri, çok sayıda ürün sürümünde birden fazla platformu (5'ten fazla) destekledi. Tarif ettiğin zorlukların çoğu, biraz farklı bir şekilde de olsa karşılaştığımız şeylerdi. Özel bir DB ye sahip olduk, bu yüzden o arenada aynı tür problemler yaşamadık.

Yapımız sizinkine benziyordu, ancak kodumuz için tek bir havuzumuz vardı. Platforma özel kod, kod ağacındaki kendi proje klasörlerine gitti. Ortak kod, ait olduğu katmana bağlı olarak ağacın içinde yaşadı.

Yapılmakta olan platforma bağlı olarak koşullu derleme yaptık. Bunu sürdürmek bir tür acı oldu, ancak yalnızca platforma özel katmana yeni modüller eklendiğinde yapılması gerekiyordu.

Tüm kodu tek bir depoda bulundurmak, aynı anda birden fazla platformda ve sürümde hata düzeltmeleri yapmamızı kolaylaştırdı. Yeni bir kodun ilgili olmayan bir platformu kırması durumunda tüm platformlar için bir durma noktası görevi görecek otomatik bir kurulum ortamımız vardı.

Bunu caydırmaya çalıştık, ancak bir platformun, genel olarak ortak kodda bulunan platforma özgü bir hatayı temel alan bir düzeltmeye ihtiyaç duyduğu durumlar olabilir. Modülü kaçak görünmeden derlemeye koşullu olarak izin verebilirsek, önce bunu yaparız. Olmazsa, modülü ortak alanın dışına çıkartacağız ve platforma özel olarak zorlayacağız.

Veri tabanı için platforma özel sütunlar / modifikasyonlar içeren birkaç tablomuz vardı. Tablonun her platform sürümünün temel bir işlevsellik düzeyi karşıladığından emin oluruz, böylece ortak kod platform bağımlılıkları hakkında endişelenmeden başvuru yapabilir. Platforma özel sorgular / manipülasyonlar, platform proje katmanlarına itildi.

Yani, sorularınızı cevaplamak için:

  1. Çok, birlikte çalıştığım en iyi takımlardan biriydi. O sırada kod temeli 1M loc civarındaydı. Yaklaşımı seçemedim, ama oldukça iyi geçti. Görüştüğümde bile, işleri idare etmenin daha iyi bir yolunu görmedim.
  2. Cevabımda bahsettiğim nüanslarla önerdiğiniz ikinci yaklaşımı öneririm.
  3. Aklıma gelen hiçbir kitap yok, ama çok platformlu gelişimi bir başlangıç ​​olarak araştırırdım.
  4. Bazı güçlü yönetişim kur. Kodlama standartlarınızın izlendiğinden emin olmanın anahtarıdır. Bu standartlara uymak, işleri yönetilebilir ve sürdürülebilir kılmanın tek yoludur. Takip ettiğimiz modeli kırmak için ateşli bir zevkten payımız vardı, ancak bu itirazların hiçbiri kıdemli geliştirme ekibini asla sallamadı.

Deneyiminizi paylaştığınız için teşekkür ederiz. Sadece daha iyi anlamak için: Sizin durumunuzda bir platform nasıl tanımlanır? Windows, Linux, X86 / x64? Veya farklı müşteriler / ortamlar ile ilgili daha fazla bir şey mi? 4'te iyi bir noktaya değiniyorsunuz) Bence bu bizim sahip olduğumuz sorunlardan biri. Çok akıllı ve nitelikli insanlardan oluşan bir ekibimiz var, ancak herkesin işlerin nasıl yapılacağı konusunda biraz farklı fikirleri var. Mimariden açıkça sorumlu biri olmadan ortak bir strateji üzerinde anlaşmak zordur ve hiçbir şeyi değiştirmeden tartışmalarda kendinizi kaybetme riskiyle karşı karşıya kalırsınız.
aKzenT

@aKzenT - evet, fiziksel donanım ve işletim sistemi platformları demek istedim. Bazıları bir lisans modülü tarafından seçilebilen geniş bir özellik setimiz vardı. Ve geniş bir donanım yelpazesini destekledik. Bununla ilgili olarak, kod ağacı için bu katmanda kendi dizinleri olan bir sürü cihaza sahip ortak bir katman dizinimiz vardı. Yani şartlarımız gerçekten bulunduğunuz yerden o kadar uzak değildi. Üst düzey devlerimiz birbirimizle olan tartışmaları canlandırırdı, ancak bir kez kolektif bir karar alındıktan sonra herkes çizgiyi yapmayı kabul etti.

4

Yıllarca benzer sorunları olan Emeklilik İdaresi başvurusunda çalıştım. Emeklilik planları şirketler arasında oldukça farklıdır ve hesaplama mantığı ve raporlarının uygulanması için oldukça özel bilgiler ve ayrıca çok farklı veri tasarımları gerektirir. Mimarlığın bir kısmının sadece kısa bir tanımını verebilirim, ama belki de yeterince fikir verecektir.

2 ayrı ekibimiz vardı: çekirdek sistem kodundan sorumlu olan bir çekirdek geliştirme ekibi (yukarıdaki% 80 paylaşılan kodunuz olurdu) ve emeklilik sistemlerinde etki alanı uzmanlığı olan ve öğrenen müşteriden sorumlu bir uygulama ekibi vardı. gereksinimler ve kodlama komut dosyaları ve müşteri için raporlar.

Tüm tablolarımızı Xml'de tanımladık (varlık çerçevelerinin zaman testinden geçirildiği ve ortak olduğu zamandan önce). Uygulama ekibi tüm tabloları Xml'de tasarlar ve çekirdek uygulamadan tüm tabloları Xml'de oluşturması istenebilir. Her müşteri için VB script dosyaları, Crystal Reports, Word docs vb. (Diğer uygulamaların yeniden kullanılmasını sağlamak için Xml'de yerleşik bir miras modeli vardı).

Çekirdek uygulama (tüm istemciler için bir uygulama), söz konusu müşteri için bir istek geldiğinde tüm istemciye özel öğeleri önbelleğe alır ve seri hale getirilip aktarılabilen ortak bir veri nesnesi (uzak bir ADO kayıt kümesi gibi) oluşturur. etrafında.

Bu veri modeli, varlık / etki alanı nesnelerine göre daha az kaygandır, ancak oldukça esnek, evrenseldir ve bir çekirdek kod kümesi tarafından işlenebilir. Belki de sizin durumunuzda, temel varlık nesnelerinizi yalnızca ortak alanlarla tanımlayabilir ve özel alanlar için ek bir Sözlüğe sahip olabilirsiniz (özel alanlar için meta verilere sahip olması için varlık nesnenize bir tür veri tanımlayıcı kümesi ekleyin). )

Çekirdek sistem kodu ve uygulama kodu için ayrı kaynak havuzlarımız vardı.

Çekirdek sistemimiz aslında çok standart bazı ortak hesaplama modülleri dışında çok az iş mantığına sahipti. Çekirdek sistem, ekran jeneratörü, senaryo koşucusu, rapor jeneratörü, veri erişimi ve taşıma katmanı olarak işlev gördü.

Çekirdek mantığı ve özelleştirilmiş mantığı bölümlere ayırmak zorlu bir mücadeledir. Bununla birlikte, her bir istemci için çalışan sistemin birden fazla kopyası yerine, birden çok istemciyi çalıştıran bir çekirdek sistemin olmasının her zaman daha iyi olduğunu hissettik.


Geri dönüşünüz için teşekkür ederiz. Bir sözlükte ek alanların olması fikrini seviyorum. Bu, bir varlığın tek bir tanımını yapmamızı ve müşteriye özel tüm şeyleri bir sözlüğe koymamızı sağlar. ORM sarmalayıcımızla (Entity Framework) çalışmasını sağlamanın iyi bir yolu olup olmadığından emin değilim. Ayrıca, her özellik / modül için bir model yerine genel olarak paylaşılan bir veri modeline sahip olmanın gerçekten iyi bir fikir olup olmadığından emin değilim.
aKzenT

2

Daha küçük bir sistemde (20 kloc) çalıştım ve DI ve yapılandırmanın istemciler arasındaki farklılıkları yönetmenin harika yolları olduğunu, ancak sistemin istifade etmesini engellemek için yeterli olmadığını gördüm. Veri tabanı, sabit bir şemaya sahip, uygulamaya özel bir kısım ile özel bir XML yapılandırma belgesi ile tanımlanan müşteriye bağlı kısım arasında bölünmüştür.

Mercurial'da tek bir şubeyi teslim edilebilir gibi yapılandırılmış ancak kurgusal bir müşteri için markalı ve yapılandırılmış olarak tuttuk. Hata düzeltmeleri bu projeye dahil edilmiştir ve yeni çekirdek işlevsellik gelişimi sadece orada gerçekleşir. Gerçek müşterilere verilen sürümler, kendi depolarında depolanan şubelerdendir. El ile yazılmış sürüm numaraları aracılığıyla kodda yapılan büyük değişiklikleri takip eder ve taahhüt numaralarını kullanarak hata düzeltmelerini izleriz.


Müşteriler arasında aynı olan çekirdek kütüphaneleri birbirinden ayırdınız mı yoksa tüm ağacı mı çatalladınız? Ana hattan bireysel çatallara kadar birleşmeyi düzenliyor musunuz? Ve eğer evet ise günlük birleştirme rutin maliyeti ne kadar zaman aldı ve zaman baskısı başladığında bu prosedürün parçalanmasını nasıl önlediniz (her zaman projenin bir noktasında olduğu gibi)? Çok fazla soru için özür dilerim: p
aKzenT

Tüm ağacı çatallıyoruz, çünkü müşteri talepleri derhal sistem bütünlüğünden önce geliyor. Ana sistemden birleştirme, ticari ve diğer araçlar kullanılarak elle yapılır ve genellikle kritik hatalar veya büyük özellik güncellemeleri ile sınırlıdır. Hem birleştirme maliyeti nedeniyle hem de çoğu müşteri kendi sistemlerini barındırdığından ve kurulum maliyetlerini değer koymadan uygulamak istemediğimiz için, güncellemeleri büyük sıkıntılara bırakmaya çalışıyoruz.
Dan Monego

Merak ediyorum: IIRC mercurial git'e benzer bir DVCS. Şubeler arasında bu birleşme yapmanın Subversion veya diğer geleneksel VCS ile karşılaştırıldığında herhangi bir avantajı fark ettiniz mi? Az önce yıkılmayı kullanarak tamamen gelişmiş 2 dal arasında çok acı verici bir birleşme süreci bitirdim ve git kullanırsak daha kolay olacağını düşünmüştüm.
aKzenT

Mercurial ile birleşme Vault olan önceki aracımızla birleştirmekten çok, çok daha kolay. Başlıca avantajlarından biri, mercurial'ın uygulamada değişiklik tarihini öne ve ortaya koymakta gerçekten iyi olması ve yapılanın nerede yapıldığını takip etmeyi kolaylaştırmasıdır. Bizim için en zor kısım, mevcut şubelerin taşınmasını sağlamaktı - eğer iki şubeyi birleştiriyorsanız, mercurial ikisinin de aynı kökü olmasını gerektirir, bu yüzden bu kurulumu elde etmek için son bir kez elle birleştirme gerekliydi.
Dan Monego

2

Açıkladığım problem hakkında doğrudan bir deneyimim olmadığı için korkuyorum ama bazı yorumlarım var.

İkinci seçenek, kodu merkezi bir depoya (uygulanabilir olduğu kadar) bir araya getirme ve kişiselleştirme için mimarlık yapmayı (yine uygulanabilir olduğu kadar) neredeyse kesinlikle uzun vadede gitmenin yoludur.

Sorun, oraya nasıl gitmeyi planladığınız ve ne kadar süreceği.

Bu durumda, bir kerede depoda (geçici olarak) uygulamanın birden fazla kopyasına sahip olmak muhtemelen tamamdır.

Bu, yavaş yavaş tek bir dokunuşta yapmak zorunda kalmadan doğrudan özelleştirmeyi destekleyen bir mimariye geçmenizi sağlayacaktır.


2

İkinci yaklaşım daha zarif görünüyor, ancak bu yaklaşımda birçok çözülmemiş sorunumuz var.

Birbiri ardına bu sorunların çözülebileceğinden eminim. Sıkışırsanız, bu konuyla ilgili SO ya da SO'ya sorun.

Diğerlerinin de belirttiği gibi, bir merkezi kod temeli / bir veri havuzuna sahip olmak, tercih etmeniz gereken seçenektir. Örnek sorunuzu cevaplamaya çalışıyorum.

Örneğin: modelinizdeki / veritabanınızdaki değişiklikleri / eklemeleri nasıl ele alırsınız. Güçlü bir şekilde yazılmış varlıklara sahip olmak için .NET'i Entity Framework ile kullanıyoruz. Veri modelimizi karıştırmadan bir müşteri için gerekli olan ancak başka bir müşteri için yararsız olan özellikleri nasıl kullanabileceğimizi anlamıyorum.

Bunların hepsini gerçek dünya sistemlerinde gördüğüm bazı olasılıklar var. Hangisini seçmeniz durumunuza bağlıdır:

  • dağınıklığı belli bir dereceye kadar yaşamak
  • "CustomAttributes" (adları ve türlerini tanımlayan) ve "CustomAttributeValues" tablolarını (örneğin, sayı olsalar bile bir dize temsili olarak depolanan değerler için) bir tablo sunun. Bu, her bir müşteri için ayrı ayrı değerlere sahip olacak şekilde yükleme veya çalışma zamanında bu gibi özellikler eklemenize izin verecektir. Her bir özel özelliğin veri modelinizde "görünür" olarak modellenmesini istemeyin.

  • Şimdi bu kodda nasıl kullanılacağı açık olmalıdır: bu tablolara erişmek için sadece genel bir koda ve bu öznitelikleri doğru bir şekilde yorumlamak için ayrı bir koda (belki de sizin için ayrı bir eklenti DLL dosyasında)

  • Başka bir alternatif, her varlık tablosuna ayrı bir XML dizesi ekleyebileceğiniz büyük bir dize alanı vermektir.
  • Bazı kavramları genelleştirmeye çalışın, böylece farklı müşteriler arasında daha kolay tekrar kullanılabilirler. Martin Fowler'in " Analiz kalıpları " kitabını öneririm . Her ne kadar bu kitap yazılımı önceden kişiselleştirmekle ilgili olmasa da, sizin için de yararlı olabilir.

Ve özel kod için: Ürününüze özellikle müşteriye özel komut dosyaları eklemek için bir komut dosyası dili eklemeyi deneyebilirsiniz. Bu şekilde yalnızca kodunuzla müşteriye özel kod arasında net bir çizgi oluşturmazsınız, müşterilerinizin de sistemi kendi başlarına bir dereceye göre özelleştirmelerine izin verebilirsiniz.


Özel özellikleri saklamak için CustomAttributes veya XML sütunları eklerken gördüğüm sorunlar, yeteneklerinde çok sınırlı olmalarıdır. Örneğin, bu özelliklere göre sıralama, gruplama veya filtreleme yapmak çok zordur. Bir keresinde, fazladan bir öznitelik tablosu kullanan bir sistem üzerinde çalıştım ve bu özel öznitelikleri korumak ve işlemek giderek daha karmaşık hale geldi. Bu sebeplerden dolayı, bu nitelikleri orijinaline 1: 1 olarak eşlenen ekstra bir tabloya sütun olarak koymak yerine düşünüyordum. Bunların nasıl tanımlanacağı, sorgulanacağı ve yönetileceği sorunu yine de aynıdır.
aKzenT

@aKzenT: Özelleştirilebilirlik bedava gelmiyor, kullanım kolaylığı ile kişiselleştirilebilirlikten kurtulmanız gerekiyor. Benim genel önerim, sistemin çekirdek kısmının herhangi bir şekilde herhangi bir özel parçadan, sadece tam tersinden bağımlı olduğu bağımlılıklar getirmemenizdir. Örneğin, müşteri 1 için bu "fazladan tabloları" tanıtırken, bu tabloları ve ilgili kodu müşteri 2 için dağıtmaktan kaçınabilir misiniz? Cevabınız evet ise, çözüm tamam.
Doktor Brown

0

Sadece böyle bir uygulama yaptım. Satılan birimlerin% 90'ının herhangi bir değişiklik olmadığı gibi satıldığını söyleyebilirim. Her müşterinin kendine özel bir cildi vardı ve biz o cildin içindeki sistemi hazırladık. Bir mod geldiğinde çekirdek bölümleri etkiledi, IF dallanmasını kullanmaya çalıştık . Aynı bölüm için mod # 2 girdiğinde , gelecekteki genişlemeye izin verilen bir şekilde CASE mantığına geçtik . Bu, küçük taleplerin çoğunu ele alıyor gibiydi.

Küçük herhangi bir küçük özel istek, Case mantığı uygulanarak gerçekleştirildi.

Eğer modlar iki köklü olsaydı, bir klon inşa ettik (ayrı dahil) ve farklı modülü dahil etmek için etrafına bir CASE sardık.

Çekirdek üzerindeki hata düzeltmeleri ve değişiklikler tüm kullanıcıları etkiledi. Üretime geçmeden önce geliştirme aşamasında iyice test ettik. Her zaman herhangi bir değişikliğe eşlik eden e-posta bildirimlerini gönderdik ve ASLA, ASLA, ASLA, Cuma günleri üretim değişikliği yapamadık ... ASLA.

Çevremiz Klasik ASP ve SQL Server'dı. Bir spagetti kod dükkanı DEĞİLDİK ... Her şey Includes, Subroutines ve Functions kullanılarak modülerdi.


-1

A ile% 80 işlevsellik paylaşan B'nin gelişimini başlatmam istendiğinde, şunu yapacağım:

  1. A Klonu ve değiştirin.
  2. Hem A hem de B'nin kullanacakları C'ye paylaştığı işlevselliği çıkarın.
  3. A'yı hem B'nin hem de kendisinin ihtiyaçlarını karşılayacak kadar yapılandırılabilir yapın (bu nedenle B, A'ya gömülüdür).

1'i seçtin ve durumunuza iyi uymuyor gibi görünüyor. Göreviniz hangisinin 2 ve 3'ün daha uygun olduğunu tahmin etmektir.


1
Sesler kolay, ama pratikte bunu nasıl? Yazılımınızı, bir süre sonra elde edilemez hale gelen "if (customer1)" ile karıştırmadan nasıl bu kadar yapılandırılabilir hale getirirsiniz?
aKzenT

@aKzenT Bu yüzden seçmeniz için 2 ve 3 bıraktım. Yapılandırma yoluyla yapmak Customer1 proje destek customer2 ihtiyaçlarına göre gerekli değişikliklerin tür kodunu yapacak olursa unmaintainable sonra 3. yapmayın
Moshe Revah

"İf (customer1)" yerine "if (seçenek1)" yapmayı tercih ederim. Bu sayede N opsiyonu ile birçok müşteriyi yönetebiliyorum. Örneğin, N boolean seçenekleriyle 2 ^ N müşterisini yönetebilirsiniz, yalnızca N 'if' ... "if (customer1)" stratejisiyle yönetmek mümkün değildir, bu da 2 ^ N 'if' gerektirir.
Fil
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.