Як ви організовуєте високоіндивідуальне програмне забезпечення?


28

Я працюю над великим програмним проектом, який дуже налаштований для різних клієнтів у всьому світі. Це означає, що у нас, можливо, 80% код, який є загальним для різних клієнтів, але також багато коду, який повинен змінюватися від одного клієнта до іншого. Раніше ми займалися розробкою в окремих сховищах (SVN), і коли розпочався новий проект (у нас мало, але великих клієнтів), було створено ще одне сховище, засноване на тому, що минулий проект має кращу основу коду для наших потреб. Це працювало в минулому, але ми зіткнулися з кількома проблемами:

  • Помилки, які виправлені в одному сховищі, не виправлені в інших сховищах. Це може бути проблемою організації, але мені важко виправити та виправити помилку у 5 різних сховищах, маючи на увазі, що команда, яка підтримує це сховище, може бути в іншій частині світу, і у нас немає їх тестового середовища , не знаю їх розкладу чи вимог, які вони пред'являють ("помилка" в одній країні може бути "функцією" в іншій)
  • Особливості та вдосконалення для одного проекту, які також можуть бути корисні для іншого проекту, втрачаються або якщо вони використовуються в іншому проекті часто викликають великі головні болі, зливаючи їх з однієї бази коду в іншу (оскільки обидві гілки могли розроблятися незалежно протягом року ).
  • Переробки та покращення коду, зроблені в одній галузі розвитку, або втрачаються, або приносять більше шкоди, ніж користі, якщо вам доведеться об'єднати всі ці зміни між гілками.

Зараз ми обговорюємо, як вирішити ці проблеми, і поки що придумали такі ідеї, як вирішити цю проблему:

  1. Продовжуйте розробку в окремих гілках, але краще організовуйте їх за допомогою центрального сховища, де загальні виправлення помилок об'єднуються у них, і всі проекти регулярно (наприклад, щодня) об'єднують зміни з цього центрального сховища у свої власні. Для цього потрібна величезна дисципліна та багато зусиль для злиття між гілками. Тож я не переконаний, що це спрацює, і ми можемо дотримуватися цієї дисципліни, особливо коли тисне час.

  2. Відмовитися від окремих гілок розробки та мати центральне сховище коду, де живе весь наш код, і робимо наше налаштування, маючи підключаються модулі та параметри конфігурації. Ми вже використовуємо контейнери для введення залежностей для вирішення залежностей у нашому коді, і ми дотримуємося схеми MVVM у більшості нашого коду, щоб чітко відокремити бізнес-логіку від нашого інтерфейсу.

Другий підхід здається більш елегантним, але в нас є багато невирішених проблем. Наприклад: як обробляти зміни / доповнення у вашій моделі / базі даних. Ми використовуємо .NET з Entity Framework, щоб мати чітко набрані сутності. Я не бачу, як ми можемо обробляти властивості, необхідні для одного клієнта, але марні для іншого клієнта, не захаращуючи нашу модель даних. Ми думаємо вирішити це в базі даних, використовуючи супутникові таблиці (маючи окремі таблиці, де живуть наші додаткові стовпці для конкретного об'єкта з відображенням 1: 1 до вихідної сутності), але це лише база даних. Як ви справляєтесь з цим у коді? Наша модель даних живе в центральній бібліотеці, яку ми не змогли б розширити для кожного клієнта, використовуючи такий підхід.

Я впевнений, що ми не єдина команда, яка бореться з цією проблемою, і я шокована тим, що знайшла так мало матеріалів на цю тему.

Тож мої запитання такі:

  1. Який у вас досвід роботи з високоіндивідуальним програмним забезпеченням, який підхід ви обрали і як це працювало для вас?
  2. Який підхід ви рекомендуєте і чому? Чи є кращий підхід?
  3. Чи є якісь хороші книги чи статті на тему, які ви можете порекомендувати?
  4. Чи є у вас конкретні рекомендації щодо нашого технічного середовища (.NET, Entity Framework, WPF, DI)?

Редагувати:

Дякую за всі пропозиції. Більшість ідей відповідають тим, які ми вже мали у нашій команді, але дуже корисно побачити досвід, який ви мали з ними, та поради щодо їх кращої реалізації.

Я досі не впевнений, яким шляхом ми підемо, і я не приймаю рішення (поодинці), але я передам це в своїй команді і впевнений, що це буде корисно.

На даний момент тенор, здається, є єдиним сховищем, використовуючи різні модулі, визначені клієнтом. Я не впевнений, що наша архітектура відповідає цьому чи скільки ми повинні вкласти, щоб пристосувати її, тому деякі речі можуть деякий час жити в окремих сховищах, але я думаю, що це єдине довгострокове рішення, яке буде працювати.

Тож ще раз дякую за всі відповіді!


Розглянемо трактування таблиць баз даних як коду.

Ми робимо це вже в тому сенсі, що в нашому підривному сховищі є сценарії бази даних, але це насправді не вирішує проблем, згаданих вище. Ми не хочемо, щоб у нашій базі даних були таблиці стилів Key-Value, оскільки вони виникають з великою кількістю проблем. Тож як ви дозволяєте доповнення до вашої моделі для окремих клієнтів, зберігаючи спільне сховище коду для всіх?
aKzenT

Відповіді:


10

Здається, що основна проблема - це не просто обслуговування сховища коду, а відсутність відповідної архітектури .

  1. У чому полягає суть / суть системи, яку завжди поділять усі системи?
  2. Які покращення / відхилення потребує кожен замовник?

Рамка або стандартна бібліотека охоплює перше, тоді як остання буде реалізовуватися як доповнення (плагіни, підкласи, DI, що б не мало сенсу для структури коду).

Можливо, допомогла б також система управління джерелами, яка керує галузями та розподіленим розвитком; Я фанат Mercurial, інші віддають перевагу Git. Рамка була б основною гілкою, кожна спеціальна система, наприклад, була б підгалузями.

Конкретні технології, що застосовуються для впровадження системи (.NET, WPF, що завгодно), в основному не мають значення.

Отримати це право непросто , але це дуже важливо для довгострокової життєздатності. І звичайно, чим довше ви чекаєте, тим більший технічний борг вам доведеться мати.

Книга « Архітектура програмного забезпечення: організаційні принципи та шаблони» може бути корисною.

Удачі!


3
Так. Хоча архітектура часто більше психологічна річ, ніж технічна річ. Якщо ви зосередитесь на продукті, тоді ви закінчите роботу, де компоненти корисні лише для цього продукту. Якщо, з іншого боку, ви зосереджуєтесь на створенні набору бібліотек, які будуть в цілому кориснішими, тоді ви будуєте набір можливостей, які можна розгорнути в більш широкому діапазоні ситуацій. Ключовим, безумовно, є пошук правильного балансу між цими двома крайнощами для вашої конкретної ситуації.
Вільям Пейн

Я думаю, що між багатьма нашими відділеннями існує велика спільна частина (> 90%), але останні 10% завжди знаходяться в різних місцях, тому є дуже мало компонентів, де я не можу уявити певні зміни, пов'язані з клієнтом, за винятком деяких бібліотек утиліти, які не містять жодної логіки бізнесу.
aKzenT

@aKzenT: хммм ... не уявляй, замість цього вимірюй. Огляньте код і перегляньте всі місця, де відбулася налаштування, складіть список модифікованих компонентів, відзначте, як часто кожен компонент був модифікований, і подумайте про види та закономірності модифікацій, які були зроблені насправді. Вони косметичні чи алгоритмічні? Вони додають чи змінюють базову функціональність? У чому причина кожного типу змін? Знову ж таки, це важка робота , і, можливо, вам не сподобаються наслідки того, що ви відкриєте.
Стівен А. Лоу

1
Я прийняв це як відповідь, тому що ми не можемо прийняти це рішення, перш ніж подумати більше про нашу архітектуру, визначити частини, які є загальними, або ТРІБНО бути загальними, а потім побачити, чи можемо ми жити з одним сховищем або чи потрібна розгортання (для момент як мінімум). Ця відповідь відображає цей найкращий ІМО. Дякую за всі інші публікації, хоча!
aKzenT

11

Одна компанія, над якою я працював, мала ту саму проблему, і підхід до вирішення цієї проблеми був такий: Створено загальну основу для всіх нових проектів; сюди входять усі речі, які повинні бути однаковими у кожному проекті. Наприклад, інструменти для генерації форм, експорт в Excel, ведення журналів. Доклали зусиль, щоб переконатися, що ця спільна рамка лише вдосконалюється (коли новий проект потребує нових можливостей), але ніколи не розвивається.

Виходячи з цієї структури, в окремих сховищах підтримувався специфічний для клієнта код. Коли це корисно або необхідно, виправлення помилок та вдосконалення копіюються між проектами (з усіма застереженнями, описаними в питанні). Однак корисні в усьому світі вдосконалення входять у загальні рамки.

Маючи все в загальній кодовій базі для всіх клієнтів, є деякі переваги, але з іншого боку, читання коду стає важким, коли існує незліченна кількість ifs, щоб змусити програму поводитися по-різному для кожного клієнта.

EDIT: Один анекдот, щоб зробити це зрозумілішим:

Домен цієї компанії - управління складом, і одним із завдань системи управління складом є пошук вільного місця зберігання вхідних товарів. Звучить легко, але на практиці потрібно дотримуватись багатьох обмежень та стратегій.

В один момент часу керівництво попросило програміста зробити гнучкий параметризований модуль для пошуку місць зберігання, який реалізував кілька різних стратегій і повинен був використовуватися у всіх наступних проектах. Благородні зусилля спричинили складний модуль, який було дуже важко зрозуміти та підтримувати. У наступному проекті керівник проекту не зміг зрозуміти, як змусити його працювати на цьому складі, і розробник згаданого модуля пішов, тому він врешті-решт проігнорував його і написав спеціальний алгоритм для цього завдання.

Через кілька років схема складу, де цей модуль спочатку використовувався, змінилася, і модуль при всій своїй гнучкості не відповідав новим вимогам; тож я і замінив його на спеціальний алгоритм.

Я знаю, що LOC - це не дуже хороший показник, але все одно: розмір "гнучкого" модуля становив ~ 3000 LOC (PL / SQL), тоді як спеціальний модуль для тієї ж задачі займає ~ 100..250 LOC. Тому, намагаючись бути гнучким, надзвичайно збільшив розмір кодової бази, не здобувши багаторазового використання, на який ми сподівалися.


Дякуємо за ваш відгук. Це розширення до першого описаного рішення, і ми також думали про це. Однак, оскільки більшість наших бібліотек використовують деякі основні об'єкти, і ці основні об'єкти зазвичай розширені для одного або іншого клієнта, я думаю, що ми могли б помістити лише небагато бібліотек у цей основний сховище. Наприклад, у нас визначена сутність "Клієнта", а ORM відображена в одній бібліотеці, яка використовується майже всіма іншими нашими бібліотеками та програмами. Але кожен клієнт має кілька додаткових полів, які він повинен додати до "Клієнта", тому нам потрібно роздрібнити цю бібліотеку, а отже, і всі бібліотеки залежно від неї.
aKzenT

3
Наша ідея уникати незліченних "ifs" полягає в тому, щоб широко використовувати ін'єкцію залежностей та обмін повноцінними модулями для різних клієнтів. Не впевнений, як це вийде, хоча. Як цей підхід працював для вас?
aKzenT

+1, це в основному відповідає моєму досвіду проектів, які добре справляються з цим. Якщо ви збираєтеся використовувати підхід "ifs для різних клієнтів", 2 бали: 1. Не робіть if (customer1) ..., а замість цього if (configurationOption1) ... і маєте параметри конфігурації для кожного клієнта. 2. Намагайся цього не робити! Можливо, 1% часу буде кращим (зрозумілішим / легкодоступним) варіантом, ніж наявність модулів, що відповідають конфігурації.
vaughandroid

@Baqueta: Просто для уточнення: ви рекомендуєте використовувати модулі для кожного клієнта замість параметрів конфігурації (якщо), так? Мені подобається ваша ідея розмежувати функції, а не клієнтів. Таким чином, поєднання обох було б мати різні "функції модулів", які контролюються параметрами конфігурації. Потім клієнт представляється лише як набір модулів незалежних функцій. Мені дуже подобається такий підхід, але я не впевнений, як це архітектувати. DI вирішує проблему завантаження та обміну модулями, але як ви керуєте різними моделями даних між клієнтами?
aKzenT

Так, модулі на одну функцію, а потім конфігурація / вибір функцій замовника. DI було б ідеально. На жаль, мені ніколи не доводилося поєднувати ваші вимоги щодо істотного налаштування кожного клієнта з єдиною бібліотекою даних, тому я не впевнений, що мені там можуть допомогти багато ...
vaughandroid

5

Один із проектів, над якими я працював над підтримкою декількох платформ (понад 5) у великій кількості випусків продуктів. Дуже багато проблем, які ви описуєте, - це речі, з якими ми стикалися, хоча і дещо по-іншому. У нас була власна БД, тому у нас на тій арені не виникало однакових проблем.

Наша структура була схожа на вашу, але у нас було єдине сховище для нашого коду. Код конкретної платформи увійшов у власні папки проекту в кодовому дереві. Загальний код містився в дереві на основі того, до якого шару він належав.

У нас була умовна компіляція, заснована на побудованій платформі. Підтримка цього була болем, але це потрібно було робити лише тоді, коли нові модулі були додані на певному шарі платформи.

Маючи весь код у одному сховищі, нам було легко зробити виправлення помилок на кількох платформах та релізах одночасно. У нас було автоматизоване середовище побудови для всіх платформ, які слугували б задньою зупинкою у випадку, якщо новий код порушив припущену споріднену платформу.

Ми намагалися відмовитись від цього, але траплялися б випадки, коли платформа потребувала виправлення на основі помилки, пов’язаної з певною платформою, яка була інакше загальним кодом. Якби ми могли умовно змінити компіляцію, не змушуючи модуль виглядати нечітко, ми зробимо це спочатку. Якщо ні, ми б перемістили модуль із загальної території та підштовхнули його до конкретної платформи.

Для бази даних у нас було кілька таблиць, які мали конкретні стовпчики / модифікації для платформи. Ми би переконалися, що кожна версія платформи таблиці відповідає базовому рівню функціональності, тому загальний код може посилатися на неї, не турбуючись про залежності платформи. Спеціальні запити / маніпуляції щодо платформи були висунуті в шари проектів платформи.

Отже, щоб відповісти на ваші запитання:

  1. Багато, і це була одна з найкращих команд, з якими я працював. Кодова база в той час становила близько 1М локації. Мені не вдалося вибрати підхід, але це склалося досить добре. Навіть заднім числом я не бачив кращого способу поводження з речами.
  2. Я рекомендую другий підхід, який ви запропонували, з нюансами, які я зазначив у своїй відповіді.
  3. Жодної книги, про яку я не можу придумати, але я б досліджувала розробку багатоплатформ як початкову програму.
  4. Інститут сильного управління. Це ключ до того, щоб забезпечити дотримання ваших стандартів кодування. Дотримання цих стандартів - єдиний спосіб підтримувати речі керованими та реконструйованими. У нас була частка нахабних клопотань порушити модель, яку ми наслідували, але жодне з цих звернень ніколи не коливало всю старшу команду розвитку.

Дякуємо, що поділилися своїм досвідом. Просто, щоб краще зрозуміти: як визначається платформа у вашому випадку. Windows, Linux, X86 / x64? Або щось більше пов'язане з різними клієнтами / середовищами? Ви добре зазначаєте 4) Я думаю, що це одна з проблем. У нас є команда з дуже багато розумних та кваліфікованих людей, але кожен має дещо різні ідеї, як робити справи. Без того, хто чітко відповідає за архітектуру, важко домовитися про загальну стратегію, і ви ризикуєте загубитися в дискусіях, нічого не змінюючи.
aKzenT

@aKzenT - так, я мав на увазі фізичне обладнання та ОС як платформи. У нас був великий набір функцій, деякі з яких були обрані модулем ліцензування. І ми підтримували широкий набір апаратних засобів. З цим пов'язано, у нас був загальний каталог шарів, який мав купу пристроїв із власними каталогами в цьому шарі для кодового дерева. Тож наші обставини насправді були не такими далеко від того, де ти є. Наші старші благодійники мали б бадьорі дискусії між собою, але як тільки було прийнято колективне рішення, всі погодились перейти на лінію.

4

Я багато років працював над заявою Пенсійної адміністрації, яка мала подібні проблеми. Пенсійні плани сильно відрізняються між компаніями і вимагають вузькоспеціалізованих знань для впровадження логіки розрахунків та звітів, а також дуже різного дизайну даних. Я можу дати лише короткий опис частини архітектури, але, можливо, вона дасть достатню кількість ідеї.

У нас було 2 окремі команди: основна команда з розробки , яка відповідала за основний системний код (який би був на 80% загальним кодом вище), і команда з впровадження , яка володіла доменним досвідом роботи в пенсійних системах і відповідала за навчання клієнта вимоги та сценарії кодування та звіти для клієнта.

Усі наші таблиці були визначені Xml (це було до того часу, коли фреймворки сутності перевірені часом і були загальними). Команда з реалізації проектувала б усі таблиці в Xml, і основну програму можна запропонувати генерувати всі таблиці в Xml. Для кожного клієнта також були пов'язані файли сценаріїв VB, Crystal Reports, документи Word тощо. (Існувала також модель успадкування, вбудована в Xml, щоб дозволити повторне використання інших реалізацій).

Основна програма (одна програма для всіх клієнтів) кешуватиме всі специфічні для клієнта речі, коли надходить запит для цього клієнта, і він генерує загальний об'єкт даних (на зразок віддаленого набору записів ADO), який може бути серіалізований та переданий навколо.

Ця модель даних є менш гладкою, ніж об'єкти / доменні об'єкти, але вона дуже гнучка, універсальна і може оброблятися одним набором основного коду. Можливо, у вашому випадку ви можете визначити базові об'єкти сутності лише із загальними полями та мати додатковий словник для спеціальних полів (додати якийсь набір дескрипторів даних до вашого об'єкта сутності, щоб у ньому були метадані для спеціальних полів. )

У нас були окремі сховища джерел для основного системного коду та для коду реалізації.

Наша основна система насправді мала дуже маленьку бізнес-логіку, крім деяких дуже стандартних модулів обчислення. Основна система функціонувала як: генератор екрана, сценарій запуску, генератор звітів, доступ до даних та транспортний рівень.

Сегментування основної логіки та індивідуальної логіки є складним завданням. Однак ми завжди вважали, що краще мати одну основну систему, яка працює з декількома клієнтами, а не декілька копій системи, що працює для кожного клієнта.


Дякуємо за відгук. Мені подобається ідея мати додаткові поля в словнику. Це дозволило б нам мати єдине визначення сутності та помістити всі специфічні для клієнта речі у словник. Я не впевнений, хоча є хороший спосіб змусити його працювати з нашою обгорткою ORM (Entity Framework). І я також не впевнений, чи дійсно гарна ідея мати глобальну модель даних, а не модель для кожної функції / модуля.
aKzenT

2

Я працював над меншою системою (20 клоків) і виявив, що DI та конфігурація - це чудові способи управління різницями між клієнтами, але недостатньо, щоб уникнути розгортання системи. База даних розділена між конкретною частиною програми, яка має фіксовану схему, і частиною, залежною від клієнта, яка визначається через користувацький документ конфігурації XML.

Ми зберегли одну гілку в меркуріалі, яка налаштована так, ніби вона була доставлена, але була брендована і налаштована для вигаданого клієнта. Виправлення помилок розміщені в цьому проекті, і новий розвиток основної функціональності відбувається лише там. Випуски фактичним клієнтам - це відділення, які зберігаються у власних сховищах. Ми відслідковуємо великі зміни коду через написані вручну номери версій і відстежуємо виправлення помилок, використовуючи номери комітів.


Ви розмежовували основні бібліотеки, які однакові між клієнтами, або ви розщеплюєте повне дерево? Ви регулярно зливаєтесь від основної лінії до окремих вил? І якщо так, то скільки часу обійшлася щоденна процедура злиття і як ви уникли, що ця процедура розпадається, коли починається тиск часу (як це завжди відбувається в один момент проекту)? Вибачте за стільки питань: p
aKzenT

Ми розщеплюємо все дерево, головним чином тому, що запити клієнтів надходять до створення цілісності системи. Об’єднання з основної системи відбувається вручну за допомогою ртутних та інших інструментів і, як правило, обмежується критичними помилками або великими оновленнями функцій. Ми намагаємось постійно оновлювати великі нечасті шматки, як через вартість злиття, так і через те, що багато клієнтів розміщують власні системи, і ми не хочемо покладати на них витрати на встановлення без надання вартості.
Дан Монего

Мені цікаво: IIRC mercurial - це DVCS, схожий на git. Чи помітили ви якісь переваги, які роблять ці злиття між гілками порівняно з Subversion або іншими традиційними VCS? Я щойно закінчив дуже болісний процес злиття між двома повністю відомими розвиненими гілками, використовуючи підрив, і думав, чи не було б легше, якби ми використовували git.
aKzenT

Злиття з mercurial було набагато, набагато простіше, ніж об'єднання з нашим попереднім інструментом, який був Vault. Однією з головних переваг є те, що mercurial дійсно добре вкладає історію змін спереду та в центр програми, що дозволяє легко відстежувати, що було зроблено куди. Найскладнішою частиною для нас було переміщення існуючих гілок - якщо ви об'єднуєте дві гілки, для втручання потрібно, щоб вони мали один і той же корінь, тож для встановлення потрібне останнє повністю ручне злиття.
Дан Монего

2

Я боюся, що у мене немає прямого досвіду проблеми, яку ви описуєте, але я маю деякі коментарі.

Другий варіант - об'єднання коду в центральний сховище (наскільки це можливо) та архітектура для налаштування (знову ж таки, наскільки це можливо) - майже напевно шлях у довгостроковій перспективі.

Проблема полягає в тому, як ви плануєте туди потрапити і скільки часу це займе.

У цій ситуації, ймовірно, добре (тимчасово) мати більше одного примірника програми у сховищі одночасно.

Це дозволить вам поступово переходити до архітектури, яка безпосередньо підтримує налаштування, без необхідності робити це одним махом.


2

Другий підхід здається більш елегантним, але в нас є багато невирішених проблем.

Я впевнений, що будь-яку з цих проблем можна вирішити одна за одною. Якщо ви застрягли, поцікавтесь тут або на SO про конкретну проблему.

Як зазначали інші, наявність центральної бази коду / одного сховища - це варіант, який вам слід віддати перевагу. Я намагаюся відповісти на ваше прикладне запитання.

Наприклад: як обробляти зміни / доповнення у вашій моделі / базі даних. Ми використовуємо .NET з Entity Framework, щоб мати чітко набрані сутності. Я не бачу, як ми можемо обробляти властивості, необхідні для одного клієнта, але марні для іншого клієнта, не захаращуючи нашу модель даних.

Є певні можливості, усі вони я бачив у реальних системах. Кого вибрати, залежить від вашої ситуації:

  • жити з захаращенням певною мірою
  • введіть таблиці "CustomAttributes" (описуючи імена та типи) та "CustomAttributeValues" (для значень, наприклад, що зберігаються у вигляді рядкового подання, навіть якщо вони є числами). Це дозволить додавати такі атрибути під час встановлення або час виконання, маючи індивідуальні значення для кожного клієнта. Не наполягайте на тому, щоб кожен користувацький атрибут моделювався "помітно" у вашій моделі даних.

  • тепер має бути зрозуміло, як це використовувати в коді: мати лише загальний код для доступу до цих таблиць та індивідуальний код (можливо, в окремому DLL-плагіні, який залежить від вас) для правильної інтерпретації цих атрибутів

  • Інша альтернатива - надати кожній таблиці сутностей велике рядкове поле, куди ви можете додати окремий XML-рядок.
  • спробуйте узагальнити деякі поняття, щоб їх було легше використовувати для різних клієнтів. Я рекомендую книгу Мартіна Фаулера " Шаблони аналізу ". Хоча ця книга не стосується налаштування програмного забезпечення, вона може бути корисною і для вас.

А що стосується конкретного коду: ви також можете спробувати ввести мову сценарію у свій продукт, особливо для додавання сценаріїв, орієнтованих на клієнта. Таким чином, ви не тільки створюєте чітку межу між кодом та кодом, що відповідає конкретному клієнту, ви також можете дозволити своїм клієнтам налаштувати систему певною мірою самостійно.


Проблеми, які я бачу з додаванням CustomAttributes або XML стовпців для зберігання власних властивостей, полягають у тому, що вони дуже обмежені у своїх можливостях. Наприклад, сортування, групування чи фільтрування на основі цих атрибутів є дуже складним завданням. Я колись працював над системою, яка використовувала додаткову таблицю атрибутів, і вона стає все більш складною для підтримки та обробки цих спеціальних атрибутів. З цієї причини я думав замість того, щоб ставити ці атрибути як стовпці в додаткову таблицю, яка відображається 1: 1 до оригіналу. Однак проблема щодо їх визначення, запиту та управління ними залишається однаковою.
aKzenT

@aKzenT: Настроюваність не приходить безкоштовно, вам доведеться торгувати простотою використання та налаштованістю. Моя загальна пропозиція полягає в тому, щоб ви не вводили залежності, де основна частина системи будь-яким чином залежить від будь-якої спеціальної частини, лише навпаки. Наприклад, вводячи ці "додаткові таблиці" для клієнта 1, чи можна уникнути розгортання цих таблиць та відповідного коду для клієнта 2? Якщо відповідь "так", тоді рішення нормально.
Doc Brown

0

Я створив лише один такий додаток. Я б сказав, що 90% проданих одиниць було продано так само, як і ніяких модифікацій. Кожен клієнт мав власну індивідуальну шкіру, і ми обслуговували систему всередині цієї шкіри. Коли мод потрапив, що вплинуло на основні розділи, ми спробували використати розгалуження IF . Коли мод №2 з’явився для того ж розділу, ми перейшли до логіки CASE, яка дозволила розширити майбутнє. Це, здавалося, обробляє більшість незначних запитів.

Будь-які подальші незначні користувацькі запити оброблялися, застосовуючи логіку Case.

Якщо моди були двома радикальними, ми побудували клон (окремо включаємо) і обмотали навколо нього CASE, щоб включити різний модуль.

Виправлення помилок та модифікації ядра вплинули на всіх користувачів. Ми ретельно перевірили розробку перед тим, як перейти до виробництва. Ми завжди надсилали сповіщення електронною поштою, які супроводжували будь-які зміни, і НІКОЛИ, НІКОЛИ, НІКОЛИ не розміщуючи виробничі зміни по п’ятницях… НІКОЛИ.

Нашим середовищем були Classic ASP та SQL Server. Ми НЕ були магазином коду спагетті ... Все було модульним, використовуючи Включає, Підпрограми та Функції.


-1

Коли мене попросять розпочати розробку B, яка поділяє 80% функціональності з A, я або:

  1. Клон А та модифікуйте його.
  2. Витягніть функціонал, який і A, і B поділяють на C, який вони будуть використовувати.
  3. Зробіть конфігурацію, достатню для задоволення потреб як B, так і самого себе (тому B вбудований у A).

Ви вибрали 1, але це, здається, не відповідає вашій ситуації. Ваша місія полягає в тому, щоб передбачити, який із 2 та 3 найкраще підходить.


1
Звучить легко, але як це зробити на практиці? Як зробити так, щоб ваше програмне забезпечення було налаштоване, не захаращуючи його "if (customer1)", яке через деякий час стає незрозумілим.
aKzenT

@aKzenT Тому я залишив 2 та 3 для вас на вибір. Якщо зміни, необхідні для підтримки проекту customer1, потребують потреб
клієнта2

Я вважаю за краще робити "if (option1)", а не "if (customer1)". Таким чином за допомогою N варіантів я можу керувати багатьма можливими клієнтами. Наприклад, з N булевих варіантів ви можете керувати 2 ^ N клієнтами, маючи лише N 'if' ... неможливо керувати стратегією "if (customer1)", яка вимагає 2 ^ N 'if'.
Філ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.