Closed rodrigondec closed 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.
Também me pergunto se seriam models apenas dessa check list atual? Ou é um model pra cada tabela da persistência?
Um pra cada da tabela, não atualizei a lista ainda pq falta a parte de participação nas classes
Beleza. Tem problema se eu já ir começando com as tabelas que já existem ou você acha melhor eu esperar?
Pode sim
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
E tem que ver como é feito um relacionamento triplo num model desse estilo
@rodrigondec, quando vc diz "ParticipationStatus/Participation" em um único check item... significa ainda que ambos os models devem ser implementadas, certo?
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.
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.
@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.
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?
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?
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.
Sim, entendi. E percebi que faltava um email tbm agora a pouco. Irei fazer no diagrama. Crie tbm no model
E sobre location de event: #12
E comece a colocar os campos de foreign key agora. Referências:
Referência para serialização dos objetos models:
@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.
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)
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.
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.
Sobre participation, levando essas coisas em consideração acredito que pode ser tratado apenas como interesse então. @discentes-imd/backend o que acham?
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.
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.
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.
Se preferir sem as classes de relação posso dar o commit agora já pra documentação.
Com classes de relação:
Sem classes de relação (fiel aos models):
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".
Documentação alterada então 👍
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?
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?
@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.
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.
É. 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).
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.
E na verdade, eu sempre vou precisar ter a imagem em algum canto. Pq pra colocar imagem na wiki ela pega por uma url
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.
Ah, tá, então deixa. Achei que era manual.
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
No commit que vc fizer isso creio que já possa dar close nesse issue aqui
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?
Arquivo de acesso ao banco de dados? isso é feito no config.py que tem no root do repositório.
E farei isso então. Porém da pra testar os models sem o mysql, já que está com o sqllite :p
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.
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.
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.
--
--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
@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.
Dito isso, o que acham que devo fazer?
(Não quis induzir nenhuma conclusão exclusiva... quero realmente uma resposta sincera rsrs)
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.
@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
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.
Compreendi as justificativas. Acho válido também. Sem discordâncias, implementarei o que foi acordado.
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.
Criar os models de acordo com o diagrama de classes de domínio
utilizar SQLAlchemy nos models.