Como você gerencia a extensibilidade em seus sistemas multilocatário?


13

Agora, tenho alguns grandes produtos de vários inquilinos baseados na Web e logo vejo que haverá muitas personalizações específicas do inquilino.

Um campo extra aqui ou ali, talvez uma página extra ou alguma lógica extra no meio de um fluxo de trabalho - esse tipo de coisa.

Algumas dessas personalizações podem ser incorporadas no produto principal, e isso é ótimo. Alguns deles são altamente específicos e atrapalhariam todo mundo.

Tenho algumas idéias em mente para gerenciar isso, mas nenhuma delas parece ter uma boa escala. A solução óbvia é introduzir uma tonelada de configurações no nível do cliente, permitindo que vários 'recursos' sejam ativados por cliente. A desvantagem disso, é claro, é a enorme complexidade e confusão. Você pode introduzir um número realmente grande de configurações e, com o tempo, vários tipos de lógica (apresentação, negócios) podem ficar fora de controle. Depois, há o problema dos campos específicos do cliente, que imploram por algo mais limpo do que apenas adicionar um monte de campos anuláveis ​​às tabelas existentes.

Então, o que as pessoas estão fazendo para gerenciar isso? O Force.com parece ser o mestre da extensibilidade; obviamente, eles criaram uma plataforma super extensível. Você pode adicionar quase qualquer coisa com a interface do usuário baseada na Web. O FogBugz fez algo semelhante ao criar um modelo robusto de plug-in que, pensando bem, pode ter sido realmente inspirado pelo Force. Sei que eles gastaram muito tempo e dinheiro com isso e, se não me engano, a intenção era usá-lo internamente para desenvolvimento futuro de produtos.

Parece o tipo de coisa que eu poderia ser tentado a construir, mas provavelmente não deveria. :)

Um grande investimento em arquitetura conectável é o único caminho a percorrer? Como você está gerenciando esses problemas e que tipo de resultados está vendo?

EDIT: Parece que o FogBugz resolveu o problema criando uma plataforma bastante robusta e usando-a para montar suas telas. Para estendê-lo, você cria uma DLL que contém classes que implementam interfaces como ISearchScreenGridColumn e que se torna um módulo. Tenho certeza de que foi tremendamente caro construir, considerando que eles têm um grande número de desenvolvedores e trabalharam nele por meses, além de sua área de superfície ser talvez 5% do tamanho do meu aplicativo.

No momento, estou seriamente pensando se o Force.com é a maneira certa de lidar com isso. E eu sou um cara do núcleo do ASP.Net, então essa é uma posição estranha para me encontrar.


3
Eu estou supondo que esta é a questão SO, o que torna este um post transversal idêntico. Não faça isso, peça a migração da pergunta SO para aqui ou, se você estiver procurando respostas diferentes, diga-nos exatamente por que as respostas da pergunta SO não são satisfatórias.
yannis

Você está certo, a pergunta é melhor para os programadores, mas ainda parece que você obteve respostas bastante decentes. Eu editei a pergunta para fazer referência à questão SO.
maple_shaft

Respostas:


8

Eu enfrentei um problema semelhante e vou lhe contar como resolvi o problema.

  1. Em primeiro lugar, existe uma biblioteca ou mecanismo "principal". Isso basicamente comanda o programa, da mesma forma que você já descobriu. Ele lida com coisas comuns a todos os sistemas, desde a renderização de formulários dinâmicos, gerenciamento de usuários e contas, funções, seja o que for, ele faz.

  2. Cada parte do sistema está contida em um módulo. Um módulo possui dependências (outros módulos dos quais depende). Por exemplo, o sistema "principal" possui Segurança (usuários, grupos, funções, políticas de senha), Localidade (traduções, países, culturas), Repositório de Arquivos, E-mail, etc, etc. Cada módulo se define usando um arquivo xml. O arquivo xml basicamente especifica os esquemas, tabelas, classes de cálculo, definições de tela, etc. Eles são lidos quando o aplicativo inicia, se a data do arquivo foi alterada .

  3. Os módulos específicos do cliente têm seus próprios arquivos xml e sua própria DLL. Tudo se encaixa e funciona de maneira adequada e transparente com o restante do sistema. Até a substituição das visualizações MVC existentes por visualizações personalizadas, com código personalizado e modelos de visualização personalizados.

  4. Se um cliente deseja estender a funcionalidade existente, o xml / system fornece um método no qual eu posso "derivar" um módulo de outro. O novo módulo possui toda a funcionalidade existente, mas com os requisitos específicos do cliente em uma nova DLL e com um arquivo XML estendido que pode fazer as modificações. A ressalva é que eles não conseguem remover os campos existentes neste sistema, mas podemos estendê-lo e fornecer objetos e funcionalidades totalmente novos.


+1: Parece que isso levou uma ou duas horas. :)
Brian MacKay

1
@BrianMacKay, bem, assim que o trabalho foi concluído (e foi um trabalho árduo), nossos clientes ficaram muito satisfeitos com a velocidade com que poderíamos mudar as personalizações. Observe que a estrutura MVC (tanto quanto visualizações / páginas) não se presta muito bem para ser multiprojetos. Contornamos isso usando os recursos de propriedades do SVN e tendo as visualizações principais trazidas do repositório principal e usamos CSS / layouts para personalizá-lo. Mas ano, algumas boas horas: P
Moo-Juice

Apenas curioso, sobre quanto tempo você acha que levou para implementar a arquitetura em si e quantos desenvolvedores estavam envolvidos?
precisa

1
@BrianMacKay, foram 5 meses. Um desenvolvedor de interface do usuário para executar todas as visualizações CSS / HTML / Parcial, javascript, etc. e um desenvolvedor de back-end (eu) para fazer o resto.
Moo-Juice

4

Ter muita lógica de versão e camadas de código para gerenciar não está agregando valor ao seu aplicativo / site. Também requer mais poder cerebral para entender o que está acontecendo e o distrai do centro do que está fazendo.

Eu aconselho de forma diferente. Eu aconselho a manter as coisas simples e complexas.

Mantenha uma única base de código que seja a mesma para todos. Cada recurso que você adiciona é um recurso para todos. Apenas restrinja o número de itens ou armazenamento ou algo quantificável, não recursos. O motivo é quantificar coisas como armazenamento, número de entradas de dados, etc., é tão simples de programar e pode ser aplicado a apenas um pequeno punhado de coisas que realmente impedem o usuário de ficar louco no seu aplicativo. Ele só precisa ser programado com a adição de itens, em vez de fazer alguma lógica de recurso. E se os recursos estiverem vinculados a outros recursos? Torna-se muito complicado codificar isso.

Para qualificar minha resposta, construí uma estrutura de comércio eletrônico que tenho para muitos clientes e aprendi a maneira mais difícil de tentar manter todas as suas idiossincrasias. Acabei quebrando a cadeia e criei um único site de administração que é multilocatário para o comércio eletrônico. Em seguida, tenho sites que extraem dados de chamadas de serviço da web. Isso permite que equipes diferentes em diferentes tecnologias implementem recursos específicos para sites de comércio eletrônico, enquanto continuo sendo pago mensalmente na mesma infraestrutura e não me importo com o que estão fazendo. Apenas limito o uso por números, não por recursos. É muito mais fácil. O cliente pode escolher seu próprio fornecedor para criar seu site e eu não estou mais envolvido nessas decisões.

Eu também tenho um serviço de assinatura para gerenciamento de conteúdo SAAS. Isso funciona também por níveis de uso e os clientes podem adicionar seus próprios plug-ins, se quiserem, enquanto minha equipe adiciona mais recursos para todos.

Esta é apenas a minha experiência de bater minha cabeça na parede depois de tanto tempo, e depois tropeçar em algo mais simples.

Se algo sempre for específico para cada cliente, não crie uma estrutura para isso. Divida-o nas partes mais simples para que a parte da estrutura funcione para todos e, em seguida, corte o restante para que você possa estendê-lo para o indivíduo.


+1 por compartilhar sua experiência. Muito do que pareço ouvir é "este é um problema muito difícil". A realidade com a qual estou lidando é que esse sistema terá toneladas de personalizações e nem todas são apropriadas para todos ... Parece que você está dizendo que adotou a abordagem de expor uma camada de serviço e permitir que as pessoas consumam isso. como quiserem - tenho a vantagem, pelo menos, de escrever todas as extensões internamente. Mas ainda é uma bagunça para gerenciar (CNTD)
Brian MacKay

A conclusão a que chego é que você teria que escrever uma plataforma que suporte sua própria noção de componentes de interface do usuário e composição dinâmica e, em seguida, construir o aplicativo inteiro usando essa plataforma. Então, estou começando a pensar que seria inteligente escrever tudo no force.com, porque é isso que é o force.com!
precisa

Brian, FYI kitgui.com e hubsoft.com, se você estiver curioso.
Jason Sebring

2

O produto de software em que trabalho possui campos extras para extensibilidade do usuário. Cada item de dados para esses campos pode ser codificado para uma linha existente nas tabelas principais do aplicativo. Por exemplo, se o seu software contiver clientes e cada cliente uma lista de pedidos, a tabela de dados personalizável terá uma coluna para chaves estrangeiras na tabela de clientes e na tabela de pedidos, sendo que apenas uma delas será nula. Isso ou um número de tabelas, cada uma com os campos personalizados para uma tabela.

Essa é uma maneira simples e eficiente de armazenar dados extras para o usuário. Informações adicionais precisariam ser armazenadas sobre os nomes e tipos desses campos.

Isso abrange os campos personalizados para um cliente. Para um comportamento personalizado, uma API de serviços da web permitiria extensões.


1

1) A execução do código de outra pessoa nas caixas que você possui é um problema bastante difícil. Ou você pode confiar neles ou pode adiar a responsabilidade razoavelmente, terá que colocar o código em sandbox muito fortemente e ter uma dedicação acima da média à segurança. À medida que o sistema de plug-ins permite mais funcionalidades, aumenta a dificuldade de torná-lo seguro. Coisas como negação de serviço (plug-ins consomem muitos recursos), vazamento de informações (plug-ins podem acessar os dados de outros inquilinos) etc. podem ser muito reais e problemáticas, eu não participaria disso a menos que pudesse familiarizar as pessoas com esses problemas ou pessoas muito capazes, com muito tempo para acertar.

2) Sim, modularidade e personalização são difíceis. Coisas como o padrão Strategy podem ajudar (um nome sofisticado para ponteiros de função; em Java, normalmente é implementado declarando uma Interface que os usuários da classe podem implementar para personalizar o comportamento do seu código), mas você deve querer muito isolado e dissociado código para que isso funcione.

3) Em termos de dados, esse pode ser um dos exemplos úteis de armazenamento sem esquema. Se você possui um modelo de dados relacionais, é problemático ter tabelas com muitas colunas para clientes diferentes (sim, você acaba com muitas colunas anuláveis, o que é ruim ; uma razão é que é difícil ou impossível definir as restrições corretas [por exemplo, restrições que não permitem que combinações inválidas de nulos apareçam]). Adicionando tabelas específicas para o cliente (ou seja, userse foo_users, com userssegurando os campos válidos para todos os clientes e foo_userster os fileds específicas Foo) é melhor; você pode ter restrições corretas facilmente, mas seu RDBMS pode não lidar com isso normalmente (devido à explosão de junção, limites no número de tabelas etc.) e provavelmente parecerá feio no seu código.

Você pode acabar implementando um armazenamento de valor-chave em seu RDBMS, o que torna seu modelo de dados menos relacional e causará desconforto (por exemplo, bancos de dados relacionais funcionam melhor com modelos relacionais). Não tenho certeza se uma solução NoSQL se encaixará no problema geral, mas o esquema da maioria das implementações pode ser uma vantagem.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.