discentes-imd / IntegraTI-API

API RESTful para o projeto IntegraTI
https://api-integrati.herokuapp.com/
GNU General Public License v3.0
6 stars 0 forks source link

Criar os models do módulo evento #1

Closed rodrigondec closed 7 years ago

rodrigondec commented 7 years ago

Criar os models de acordo com o diagrama de classes de domínio

utilizar SQLAlchemy nos models.

Mazuh commented 7 years ago

@rodrigondec, vou começar a implementar isso hoje à noite. Há alguma documentação que você queira fazer antes? Algum requisito técnico? Algum design pattern específico? Qualquer outra consideração?

Caso não, vou implementar da forma padrão sugerida pelas documentações do flask e suas extensões (sql alchemy). Provavelmente farei algo semelhante aos models do django, porque é a única referência pessoal que tenho com Python.

Mazuh commented 7 years ago

Também me pergunto se seriam models apenas dessa check list atual? Ou é um model pra cada tabela da persistência?

rodrigondec commented 7 years ago

Um pra cada da tabela, não atualizei a lista ainda pq falta a parte de participação nas classes

Mazuh commented 7 years ago

Beleza. Tem problema se eu já ir começando com as tabelas que já existem ou você acha melhor eu esperar?

rodrigondec commented 7 years ago

Pode sim

rodrigondec commented 7 years ago

Porém lembrei de uma coisa agora. O SQLAlchemy já deve fazer as tabelas de relacionamento através de campos que nem é no django. Então colocarei só as entidades concretas na lista. E eu poderia ter documentado só elas então asuehsaue

rodrigondec commented 7 years ago

E tem que ver como é feito um relacionamento triplo num model desse estilo

Mazuh commented 7 years ago

@rodrigondec, quando vc diz "ParticipationStatus/Participation" em um único check item... significa ainda que ambos os models devem ser implementadas, certo?

rodrigondec commented 7 years ago

Significa participation_status deve ser implementado e eu não sei como fica o participation. Pq é uma tabela de relação entre 3 models: user, event e participation_status.

E tabelas de relação não precisam ser criadas, correto? Mas como faz isso? Nunca tive que fazer algo do tipo em django ou em similares.

rodrigondec commented 7 years ago

Mas tem algumas referências pra isso fáceis de serem achadas: http://stackoverflow.com/questions/23035662/how-to-three-way-many-to-many-relationship-in-flask-sqlalchemy

Segundo isso dai vc cria a tabela de relação mesmo.

rodrigondec commented 7 years ago

@Mazuh os campos sigaa_user_name e sigaa_password na verdade deverão ser user_name e password. Já que nosso login não será atrelado 100% ao sigaa.

Mazuh commented 7 years ago

Já havia retirado o prefixo pra o campo de senha. Mantive o de matrícula e nome de usuário porque eles são, de fato, inteiramente dependentes do SIGAA pra serem autenticados. Creio que o que nos falta é um campo de e-mail, que também serviria para login não-sigaa. O que você acha?

Mazuh commented 7 years ago

Reformulando o que eu disse: o prefixo sigaa_ ficou nos dois campos cuja integridade está vitalmente atrelada ao SIGAA/UFRN. Não temos condição alguma de ler um número de matrícula e certificar, com recursos próprios, que ele realmente é válido e pertence ao aluno e pode ser escrito em nosso banco de dados. O mesmo vale para o nome de usuário. Assim, pus a label pra servir de lembrete à essa questão de confiabilidade da informação estar dependente a um banco de dados externo.

Assim sendo, creio que seja melhor para nosso login próprio usar o e-mail e nossa senha, pois é mais fácil de lembrar o e-mail do que um usuário próprio. (E, caso ele queira, logue pelo Sigaa usando seu usuário e senha DE LÁ)

As observações acima não se aplicam ao campo de password, que é nosso.

Achei minha explicação meio confusa, mas acho que consegui explicar. Enfim, o que você acha?

Mazuh commented 7 years ago

Outra coisa, esqueci de dizer (perdão), também renomeei os campos de início e fim das datas dos eventos. Não faz sentido ter "event" no nome da coluna, se a coluna já é obviamente pertencente à tabela de eventos. Seria como criar uma tabela "user" e os campos "user_name", "user_pass" etc. Redundante.

rodrigondec commented 7 years ago

Sim, entendi. E percebi que faltava um email tbm agora a pouco. Irei fazer no diagrama. Crie tbm no model

rodrigondec commented 7 years ago

E sobre location de event: #12

rodrigondec commented 7 years ago

E comece a colocar os campos de foreign key agora. Referências:

rodrigondec commented 7 years ago

Referência para serialização dos objetos models:

Mazuh commented 7 years ago

@rodrigondec, fiquei um pouco preocupado com essa relação de participação de usuário com evento. Quando dei essa ideia, eu tinha em mente que ela fosse um "interesse" apenas, para não arriscarmos reinventar a roda de maneira ineficiente ou teríamos que nos preocupar de emitir certificado.

Minha preocupação é pra não entrarmos em concorrência com aplicativos mais dedicados como o do Luan (~algumacoisaHoras que eu nunca lembro o nome, puta merda~), de maior alcance como os eventos do Facebook, e de maior competência/peso burocrático para emissão de certificados como o módulo de eventos do SIGAA.

Mazuh commented 7 years ago

Outro ponto: acredito que a relação entre tags e eventos é many-to-many (o diagrama diz one-to-many, mas não sei se faz sentido?). Poderia me esclarecer melhor o que seriam essas tags?

(Acabei de reparar, inclusive, que o exemplo de many-to-many na documentação do sqlalchemy é justamente sobre tags... e páginas; o que é similar à nossa situação)

Mazuh commented 7 years ago

Eis um terceiro ponto (ainda estou aguardando resposta dos outros dois, rsrs):

Não devo fazer os models dos interesses do usuário (isso foi documentado no diagrama de classes)? E por que as tags de evento seriam diferentes das tags de interesse?

PS[1]: resolução no comentário seguinte. PS[2]: ver como ficaram as classes que escrevi na minha branch. Foram baseadas no diagrama documentado por você, mas já incorporaram as observações comentadas nesta issue (abaixo), e acho que o diagrama deveria entrar em sincronia (resolvidos os devidos conflitos de diferença). Note que classes foram removidas e campos foram modificados. E os atributos que recebem relationship(...) são propriedades, e acho que não devem entrar no UML (e seriam representados apenas pelas setas de cardinalidade), não sei... pessoalmente eu colocaria mesmo com redundância.

Mazuh commented 7 years ago

Acredito que ainda está havendo muita confusão entre as documentações das classes e as tabelas do banco de dados... :confused: As demandas/issues estão meio em conflito com a documentação.

Um trecho da documentação, que recomenda que não sejam criadas classes auxiliares, pois o próprio SQLAchemy irá se encarregar disso, pelo que entendi.

If you want to use many-to-many relationships you will need to define a helper table that is used for the relationship. For this helper table it is strongly recommended to not use a model but an actual table:

# primeiro, alguns OBJETOS, que são o que as helper tables

tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)

# a seguir, as CLASSES (usam a helper table se for conveniente), que são os models

class Page(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', secondary=tags,
        backref=db.backref('pages', lazy='dynamic'))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)

A nível de UML, as setinhas com cardinalidade já devem ser suficientes pra indicar relações one-to-many e many-to-many.

rodrigondec commented 7 years ago

Sobre participation, levando essas coisas em consideração acredito que pode ser tratado apenas como interesse então. @discentes-imd/backend o que acham?

rodrigondec commented 7 years ago

Sobre tags e event: eles são mano to many. Mas é o que eu tinha dito, fiz esse diagrama mostrando como seria realmente a implementação das tabelas.

tag tem relação de 1 para muitos com event_tag (tabela de relação) e event_tag tem relação de 1 para muitos com event. O que resulta em muitos para muitos de tag pra event se vc observar bem. image

O que eu posso fazer então já que está lhe confundindo é colocar um modelo fiel a como fica os models então. Retirando as tabelas de relação intermediária.

E sobre as tags de event serem diferentes de tags de interest do user, elas não são diferentes. Os dois apontam para tag no final. Eles apenas tem as tabelas de relação entre o user e tag ou event e tag.

rodrigondec commented 7 years ago

Sobre esse trecho que diz sobre as tables auxiliares e não models, foi isso que eu quiz dizer sobre "nossa aplicação não ve as tabelas de relaçãos". Pois não terão models pra representá-las.

rodrigondec commented 7 years ago

Se preferir sem as classes de relação posso dar o commit agora já pra documentação.

Com classes de relação: image

Sem classes de relação (fiel aos models): image

Mazuh commented 7 years ago

Sim! É mais simples desse jeito. Antes eu tava ficando bem confuso na hora de implementar, porque os models do SQLAlchemy são beeem "orientado a domínio".

rodrigondec commented 7 years ago

Documentação alterada então 👍

Mazuh commented 7 years ago

Atualiza também os atributos de Usuário e Eventos também, please.

Outra coisa, percebi que sumiram do sql-para-class alguns campos de integridade, como os de remoção lógica, de salvar data de modificação etc. Foi proposital? Não deveria estar nos models também?

rodrigondec commented 7 years ago

Esqueci de colocar esses campos, verdade. Irei colocar lá. Vou retirar tbm o participation_status então. Retirando a tabela de relação participation, deixando de ser model tbm. Beleza?

Mazuh commented 7 years ago

@rodrigondec, também creio que seria interessante você manter a documentação apenas na wiki (ela também é um repositório git, pelo que entendi, logo é bem versionada). Porque tô prevendo que na hora de dar merge nas coisas, ocorram conflitos entre arquivos não-texto, o que pode dar uma dor de cabeça amoada.

rodrigondec commented 7 years ago

Mas só daria conflito se vc alterar tais arquivos. E não tem como manter um arquito .astah na wiki. Posso manter só as imagens do diagrama. Mas de uma maneira ou outra vai ter o arquivo do astah ainda.

Mazuh commented 7 years ago

É. Faça isso. Coloque só o .astah no repositório e os .png na wiki. Porque nem sempre será você mexendo, e é melhor simplificar o workflow pro futuro. Ter o mesmo diagrama pra visualização (png) em dois lugares diferentes com upload manual é pedir pra gerar confusão no dia que você (ou outra pessoa) colocar em um lugar e esquecer de por no outro. Você também pode deixar uma brench só pra documentação.

Anyway. Adicionei as relações de usuário e evento. O usuário poderá participar em outras coisas no futuro, então coloquei como event_participation a tabela auxiliar pra evitar ambiguidades posteriormente. Também pus os campos vindos do SIGAA como String, porque um deles nunca devia ter sido String na vida (era sigaa_user_name rs) e o outro poderia estourar o limite de numérico do banco de dados (sigaa_registration_number) (adicionalmente, eles sendo String facilita a implementação de outras features irrisórias, como saber o ano de ingresso só pelo prefixo da matrícula).

rodrigondec commented 7 years ago

Mas eu não preciso alterar o arquivo da wiki quando eu do commit com o arquivo. Ele já atualiza sozinho por que é pela url do arquivo no repositório master.

image

E na verdade, eu sempre vou precisar ter a imagem em algum canto. Pq pra colocar imagem na wiki ela pega por uma url image

O que pode ser feito é deixar uma branch apenas pra documentação mesmo. E ai sempre ter que trocar pra aquela branch e dar commit no arquivo.

Mazuh commented 7 years ago

Ah, tá, então deixa. Achei que era manual.

rodrigondec commented 7 years ago

E coloque agora então aquela questão do id_user_update, id_user_insert, date_update e date_insert. Já coloquei isso no diagrama das classes

rodrigondec commented 7 years ago

No commit que vc fizer isso creio que já possa dar close nesse issue aqui

Mazuh commented 7 years ago

Tô colocando agora. Mas queria que alguém testasse antes de fechar... vou trocar meu HD amanhã e tava com uma preguiça de baixar e instalar o MySQL aqui pra ter que fazer amanhã tudo de novo... rs Também precisa de uma issue pra criar um arquivo de acesso ao banco de dados. Você poderia fazer isso, se designar e aproveitar o ensejo pra testar os models e, então, fechar ambas as issues logo após?

rodrigondec commented 7 years ago

Arquivo de acesso ao banco de dados? isso é feito no config.py que tem no root do repositório. image

E farei isso então. Porém da pra testar os models sem o mysql, já que está com o sqllite :p

Mazuh commented 7 years ago

Achei ter visto na documentação a necessidade de um database.py. E, se não me engano, precisa fazer alguma modificação no sqlite pra habilitar suporte a foreign keys, ou talvez o sqlalchemy já faça isso. De qualquer forma, preciso que alguém teste.

Também preciso checar sobre o cast de ForeignKey pra instância de model antes de fechar a discsão.

Mazuh commented 7 years ago

Queria saber com você e o @davidcardoso-ti sobre a real necessidade de ter t-o-d-o-s esses campos de integridade em cada model. Por exemplo, acho desnecessário um "usuário autor" pra a criação de usuários e pra tipos de evento.

Mazuh commented 7 years ago

Também estou tentando entender se ponho esses campos de integridade como parâmetros necessários aos métodos construtores. Tô meio perdido no tiroteio ainda.

DavidCardoso commented 7 years ago
  1. O usuário autor da tabela usuários pode ser retirado já que no Integra será o próprio usuário que "criará" o seu usuário.
  2. Nas outras tabelas, defendo manter por questões de boas práticas de DB. Pois, todo registro terá user/datetime inserção e user/timestamp update.
  3. Também sugiro que pensemos em um esquema de logs para as determinadas ações feitas pelo usuário (login com sucesso, login falho, inseriu tal registro, alterou tal registro, etc)

--

--David CardosoGerente de ProjetosDatacom - Consultoria em Tecnologia da Informação *(84) 3206-5354 / *(84) 3025-4911 / (84) 98898-5354 (claro) Skype: davidcardoso.tidavidcardoso.ti@gmail.com davidcardoso.ti@gmail.com

Mazuh commented 7 years ago

@davidcardoso-ti, mas algumas coisas eu não consigo enxergar como criáveis por usuário comum, como insert de tipos e update de arquivos. De tags eu ainda compreendo porque um usuário pode criar uma nova tag anytime, mas também já não entendo o porquê de haver um campo pra salvar quem "alterou" a tag. Da mesma forma, vejo que não devia haver sequer possibilidade de, a nível de aplicação, haver as possibilidades (acima) de inserir tipos, modificar arquivos, renomear tags.

Mazuh commented 7 years ago

Dito isso, o que acham que devo fazer?

(Não quis induzir nenhuma conclusão exclusiva... quero realmente uma resposta sincera rsrs)

rodrigondec commented 7 years ago

Eu acho que há algumas entidade que não precisarão de tudo isso tbm. Event. user e tag por exemplo. Pois tag é negligenciável para o sistema e só quem edita o Event é o organizer dele, da mesma forma o user.

DavidCardoso commented 7 years ago

@Mazuh, entendo as suas colocações. Porém, vc está analisando apenas esses casos que, realmente, podem ser dessa forma q vc está dizendo. Entretanto, pense no sistema como um todo e em como ele poderá crescer. Assim, outras funcionalidades e recursos que forem sendo adicionados poderão ter vários tipos de interações por parte do usuário e a aplicação deve estar preparada para armazenar logs mínimos (boas práticas). É melhor deixar padronizado que teremos user/date de insert e update do que ter q pensar em todos os casos separados (tendo em vista q alguns precisam e outros não ou, ainda, alguns só precisam de insert, por exemplo).

Bom, é apenas uma sugestão e recomendação, tendo em vista que isso já me ajudou muito em projetos q trabalhei.

Se aceitarem manter esses campos user/date, o que pode ser feito para amenizar a situação é deixá-los como NULLABLE. Assim, o controle do que deve ou não ser alimentado fica a nível de model/controller.

Em dom, 14 de mai de 2017 às 21:27, Marcell Guilherme Costa da Silva < notifications@github.com> escreveu:

Dito isso, o que acham que devo fazer?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/discentes-imd/IntegraTI-API/issues/1#issuecomment-301350673, or mute the thread https://github.com/notifications/unsubscribe-auth/ANNfShT3v1zooeoJue3KWEF9f7QVrsRRks5r55vngaJpZM4NRiCc .

--

--David CardosoGerente de ProjetosDatacom - Consultoria em Tecnologia da Informação *(84) 3206-5354 / *(84) 3025-4911 / (84) 98898-5354 (claro) Skype: davidcardoso.tidavidcardoso.ti@gmail.com davidcardoso.ti@gmail.com

rodrigondec commented 7 years ago

Acho válido deixar como nullable e o controller em questão decidir o que precisa ser salvo. E sobre a questão de log, irei adicionar um log no projeto. É necessário ter mesmo. E sobre ter tabelas de log para armazenar o que foi feito de alteração no bd, é uma boa prática a ser seguida.

Mazuh commented 7 years ago

Compreendi as justificativas. Acho válido também. Sem discordâncias, implementarei o que foi acordado.

Mazuh commented 7 years ago

Pronto. Foi implementado que absolutamente todas as classes model estarão com esse conjunto de atributos.

disabled = Column(Boolean)
inserted_since = Column(DateTime)
inserted_by = Column(Integer, ForeignKey('user.id_user'))
last_updated_since = Column(DateTime)
last_updated_by = Column(Integer, ForeignKey('user.id_user'))

Não coloquei nas tabelas auxiliares de relação (que não são classes). Não seria melhor usar logs ou algo do tipo pra isso, se necessário for dar track nessas atividades? O que você acha, @davidcardoso-ti (será necessária uma leitura do código pra você sacar as diferenças entre as implementações de helper tables e os model propriamente ditos)?

@rodrigondec, como há essa repetição nos models, imagino que seja interessante reunir essas coisas em uma super classe e e cada model herde desta, ao invés de default Model.