Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Page 138 sur 182 PremièrePremière ... 3888128130131132133134135136137138139140141142143144145146148 ... DernièreDernière
Affichage des résultats 4 111 à 4 140 sur 5456
  1. #4111
    Yeah, je tendrais vers la même vision.
    De toute façon, peu de recruteurs regarderont ton github, déjà qu'ils ne lisent ton CV que le jour de l'entretien .
    Mais, en de rares occasions, tu tombes sur qqun qui regarde ton github, et là avoir des repos avec un minimum d'infos peut être intéressant : au moins un readme pour dire ce que fait le projet. Perso, je déteste voir un projet sans readme, ou un readme qui rappelle juste le nom du projet. Tu es là, aucune explication, juste plein de code, youpie joie, tu passes ton chemin.
    Quant aux projets moches, honnêtement, personne ne t'en tiendra rigueur car personne n'ira lire ton code. Et quand bien même qqun de très motivé lira du code, il sera assez intelligent pour se dire que c'est un petit projet perso sans grande prétention, donc tu n'as pas 200h à passer dessus non plus.

    De ma propre expérience : en 10 ans aucun recruteur ou collègue ne savait que j'avais un github, malgré un gros lien sur mon CV. Puis un jour, une recruteuse (ma boss actuelle en fait) m'a trouvé sur github grâce à mon activité. Et c'est le meilleur taff de ma vie. Mais je pense que c'est un gros coup de chance, et mon profil est particulier (je passe ma vie dessus).
    Tu pourrais éventuellement te servir de ton github pour présenter du code lors d'un entretien tech, mais il faut que le type accepte de mettre de côté son test technique à base de QCM et de questions orales ^^, c'est plutôt rare, mais ça arrive.

    Perso, github c'est pour :
    - m'amuser et apprendre sur des projets, quitte à ce que certains aient leur petite popularité, mais ce n'est pas l'objectif (et ça n'arrive que très rarement ^^). Et du code sale, il y en a
    - me faire un référentiel de code : j'ai vu comment faire du oauth un jour au taff ? je me monte un petit projet perso qui le met aussi en œuvre, comme ça dans mon prochain taff j'aurais du code exemple (ça permet de préserver la connaissance* sans garder un zip de tes projets pro**, ce qui est interdit et très dangereux ^^) et ça fait aussi un bon exercice : souvent au taff les technos sont déjà en place, tu ne fais que "modifier" une base existante -> repartir du début, mettre les mains dans le cambouis, c'est super formateur

    * je ne sais pas pour vous, mais souvent dans un nouveau taff ou équipe, on me dit "ha mais tu as fait du Truc dans ton précédent taff ? tu peux nous aider ?". Le soucis c'est que le code tu ne l'as plus, tu as juste les grandes lignes en tête, et tu vas perdre du temps à rechercher le code, et les petites subtilités bien reloux. Now je vais sur mon github, projet demo, techno Truc ? Oui, j'ai un exemple qui va bien. Sur des technos bien relou type Spring Security, c'est salutaire.

    ** d'un employeur
    Dernière modification par gros_bidule ; 08/06/2021 à 17h31.

  2. #4112
    Ouais tout à fait ultimement ça te servira d'une manière ou d'une autre t'façon, et c'est gratos en plus. C'est tellement beau l'open source que j'en ai la larme à l'oeil

  3. #4113
    Yeah, et des contributeurs ou curieux pourront même t'apprendre des trucs
    C'est d'ailleurs un canard qui m'a montré des trucs de ouf en Kotlin

  4. #4114
    'Tain chui au taff' là. On m'a demandé de changer une tâche pour qu'elle s'exécute en parallèle du reste des tâches désormais, car trop lente. Avant ça attendait la fin d'une séquence de tâches, puis ça tournait.

    Ils m'ont dit, "surtout regarde pas le code, on te connaît, cherche pas à optimiser, juste mets nous ça en parallèle".

    Bon forcément je regarde le code, très laid mais j'ai l'habitude. J'optimise 2/3 bricoles, mais je vois rien de trop méchant. Et là je me rends compte, erreur assez classique mais bon, qu'ils ont pas compris leur framework de log. Du coup même dans un mode de log peu verbeux, genre ERROR ou PANIC, ils font quasiment autant d'opérations qu'en DEBUG ou TRACE vu qu'ils font ça au runtime (plutôt que d'avoir des binaires instrumentés de log et d'autres non) et que de toute façon y'a de gros dégueux qui ont rajouté des passes de processing avant d'arriver au log en lui même, indépendamment du niveau de log.

    Bref, TL;DR, dans des boucles critiques t'as toujours une bonne quantité de log qui est pondue, même si tu désactives les logs. En plus les logs servent à rien, font que décrire des résultats que tu peux voir à la fin t'façon. Bon ok, y'a 2 ou 3 passages intermédiaire mais très faible valeur, c'est des opérations simples.

    Le truc est passé de 14 min de runtime à 60 secondes sur un set de données de prod que j'avais, maintenant va s'agir d'être un peu diplomate pour leur expliquer comment logger proprement

    Sachant que parfois avec beaucoup de données ils ont des run d'1 heures. Si on reste sur du *14 d'optimisation ça leur ferait genre du 4 min

    EDIT: Allez, 53 secondes en enlevant les derniers logs mal faits, en plein milieu des boucles appelées 10 millions de fois en prod
    Le pire c'est qu'il en reste dans une autre librairie qu'on appelle et qui nous appartient mais bon, on verra ça plus tard. J'vais pas toucher à tous les projets d'un coup
    Dernière modification par Anonyme20240202 ; 08/06/2021 à 18h46.

  5. #4115

  6. #4116
    Bon bah le run de 1 heure 4 min en prod est devenu 110 secondes :/

    Je vais quand même mettre ça en parallèle avant de leur montrer histoire d'être safe

  7. #4117
    Protip ne dit rien et chaque vendredi tu retires 3 logs et tu prends ton après midi...Tes collègues ne méritent pas d'explication...

  8. #4118
    Hahaha pas bête.
    Le pire c'est que maintenant tourner en parallèle sera potentiellement plus lent. Car il faut que les données arrivent, donc il faudra plusieurs run, chaque run sera très court. Et y'a potentiellement un petit overhead genre si tu relances l'appli régulièrement (bon si je la laisse tourner et genre poll les données ça devrait aller). Donc certes ça devrait terminer un peu plus tôt mais le temps total sera plus long.
    M'eeeeenfin, on verra

  9. #4119
    Citation Envoyé par Frypolar Voir le message
    Tu utilises des features flags pour que cette fonctionnalité pas totalement finie ne soit pas visible en production. Ça peut aussi permettre de donner accès à cette fonctionnalité à certains clients. C’est très pratique quand ton changement est lié à un retour client. Ça te permet de valider le travail en cours de route au lieu de bosser 6 mois en sous-marin et d’avoir des retours négatifs une fois que c’est fini.
    Merci pour ta réponse Je ne connaissais pas vraiment les features flags et en regardant du côté l'Unleash c'est vraiment une bonne idée. Une moins bonne idée c'est d'aller taper dans une API externe pour voir si chaque feature est dispo (en web ça s'appelle du suicide) mais ça semble facilement implémentable en interne. J'essaierais le Trunk based dev pendant un temps du coup, voir ce que ça donne.

  10. #4120
    Citation Envoyé par Kamikaze Voir le message
    Folies
    Ptain mais cette folie de penser que paralléliser c'est moins cher et moins casse-gueule que d'optimiser (surtout du code moisi où t'as qu'à te baisser).
    Sleeping all day, sitting up all night
    Poncing fags that's all right
    We're on the dole and we're proud of it
    We're ready for 5 More Years

  11. #4121
    Citation Envoyé par Kamikaze Voir le message
    Je vais quand même mettre ça en parallèle avant de leur montrer histoire d'être safe
    « Bon, c’est bien gentil tes histoires de laugues, mais tu vois bien qu’on avait raison : avec la Parallélisation™ on est passé de 1 heure 4 minutes à 110 secondes. Je doute que tes optimisations de laugues fassent aussi bien. »

  12. #4122
    Bon, voyant que Netbeans ne fait quand même pas non plus le café (beans, café, y'a des choses à dire ), et vu que CLion est plutôt populaire ici, j'ai téléchargé la version d'essai.

    Bordel, je suis perdu, j'arrive même pas à faire un ajout de source existante à un projet tout vide.

    Un petit état des lieux : j'utilise assez peu Netbeans au final. Je développe et débogue essentiellement sous Windows, via Visual Studio en version 2017 ou 2019 avec VC++ derrière.
    Et de temps en temps, je fais un petit passage par ce bon vieux Netbeans 8.2 avec du G++ derrière. Essentiellement parce qu'Eclipse, je peux pas, c'pas possible.

    Du coup, j'entretiens un projet Visual Studio et un projet Netbeans séparément, mais avec des sources communes.
    Les paramètres des projets sont semblables dans l'esprit (répertoires de sources, bibliothèques en entrée, etc) mais je dois les maintenir tous les deux. C'est un peu chiant au début, mais après c'est peanuts à maintenir, y'a rarement des modifs. Netbeans derrière il fait une traduction en makefile, donc j'avais espéré pouvoir l'ouvrir en tant que tel sous CLion et roule ma poule, vu qu'ils disent qu'il supporte les projets à makefile, mais c'est pas aussi simple que simplement ouvrir le projet Netbeas apparemment. Oui je suis gourmand.

    Avec le temps du coup j'ai peaufiné mon rangement, dont je suis assez content, ce qui donne un truc du genre :
    Code:
    LapinRenderer/
     |- bin/
     |   '- x86_64/
     |       |- Debug/
     |       |   |- GNU-Linux/
     |       |   '- MS-Windows/
     |       '- Release/
     |           |- GNU-Linux/
     |           '- MS-Windows/
     |- LapinCore/
     |   '- build/
     |   '- nbproject/
     |   '- src/
     |   '- vsproject/
     '- LapinTests/
         '- build/
         '- nbproject/
         '- src/
         '- vsproject/
    Donc dans bin sortent les binaires. C'est rangé par plateforme et par configuration, généralement du x86_64 mais des fois j'y glisse autre chose, genre arm_64.
    A côté j'ai un répertoire par projet, le plus souvent y'a 2-3 projets, typiquement une lib statique, un projet de tests et un projet d'appli qui linkent vers la lib. Ces répertoires de projets se divisent en build (répertoire intermédiaire), src (sources), nbproject (projet Netbeans) et vsproject (projet/solution Visual Studio).

    Dans les projets Visual/Netbeans je bosse avec des chemins relatifs et je remonte puis redescends d'autant de niveaux que nécessaire pour taper dans les sources/les bibliothèques.
    Au lieu d'avoir tout au même endroit et mélanger les fichiers "privés" d'IDE séparés, j'ai des sous-dossiers pour garder le tout un peu clean.

    Du coup j'avais dans l'idée de créer un dossier "clproject" dans lequel je placerais mon projet CLion.
    Vous avez des conseils sur la bonne méthode pour créer des projets avec des sources existantes ?

  13. #4123
    Si c'est un projet CMake, tu ouvres juste le dossier. Visual fait pareil.
    De Visual vers CMake, tu as le projet cmake-generator en Python qui fait du bon taf. Il transforme un sln en CMakelist.

  14. #4124
    Citation Envoyé par vectra Voir le message
    Si c'est un projet CMake, tu ouvres juste le dossier. Visual fait pareil.
    Non malheureusement je ne pense pas. Je pense que Netbeans fonctionne avec des makefile "à l'ancienne".

    Citation Envoyé par vectra Voir le message
    De Visual vers CMake, tu as le projet cmake-generator en Python qui fait du bon taf. Il transforme un sln en CMakelist.
    Alors ça par contre c'est intéressant. Vu que j'ai déjà les solutions/projets VS de concoctés, si y'a moyen d'en tirer un projet CMake en quelques clics, c'est vendu.
    Je vais essayer ça ! Merci pour l'astuce.

  15. #4125
    (Je connais pas le cmake-generator, mais voilà comment faire ça par toi même, ou comprendre le résultat du cmake-generator)

    Avec CLion tu pourras faire fonctionner ça en 2 minutes. CLion est hautement configurable donc tu pourras aller bien plus loin mais j'te donne une idée de base pour démarrer, en gardant tout comme ça, tu pourras adapter pour faire un truc plus propre.

    Tout ce que tu as à faire c'est de placer un CMakeLists.txt dans LapinRenderer. (donc LapinRenderer/CMakeLists.txt)

    Ensuite dans ce CMakeLists.txt tu inclus tes sources, j'expliquerai après comment faire ça en relatif si tu tiens vraiment au truc "propre" (mettre les trucs dans un dossier). CLion va aussi créer un .idea a la racine du projet quand tu ouvriras LapinRenderer. Si jamais tu te loupes tu peux simplement tout supprimer et recommencer, le .idea/ n'est absolument pas important, j'explique plus tard.

    Voilà un exemple de CMakeLists.txt

    cmake_minimum_required(VERSION 3.19)
    project(test_cpp)

    set(CMAKE_CXX_STANDARD 20)

    find_package(glfw3 REQUIRED)
    find_package(Vulkan REQUIRED)

    add_executable(test_cpp main.cpp)

    target_link_libraries(test_cpp glfw Vulkan::Vulkan)
    Donc ici tout ce que tu as à faire c'est de liste chacun de tes fichiers source à la main (seulement les .cpp, les .h seront choppés naturellement en cascade via les inclusions). CLion offre la complétion dans le CMakeLists.txt donc tu pourras facilement voir les chemins.

    Donc dans mon cas je n'ai qu'un seul fichier "main.cpp", mais j'aurais pu faire "src/main.cpp" "../mon_dossier/mon_fichier.cpp" "monfichier2.cpp", faut les mettre à la suite avec un espace ou saut de ligne, etc. etc.

    Si tu as vraiment beaucoup de fichiers sources, je recommande quand même de les lister tous explicitement, tu peux faire ça via un simple "ls" ou la commande "dir" en gros sous windows. Donc un script qui te liste tes fichiers et tu choppes la liste et là fout dans le cmake.

    Ensuite une fois que tu as fait ça tu pourras browser ton code et bénéficier des fonctionnalités d'analyse de code (statique donc).

    Mais tu risques de ne pas pouvoir compiler car on ne s'est pas encore occupé des dépendances. Pour tes dépendances c'est comme avec Visual Studio et Netbeans, pas de surprise. Tu peux linker comme je le fais dans l'exemple ci dessus. Pour chopper tes dépendances le plus propre c'est find_package, mais ça requiert un setup peut-être un peu compliqué, que je décrivais plus tôt dans le topic.

    Mais pas de panique! Avec CMake de toute façon tu peux faire exactement tout ce que tu fais avec Make, donc inspire toi de ton Make et ajoute les dépendances par un autre moyen.

    Mais honnêtement la grande majorité des dépendances qui se respectent sont trouvables via find_package.

    Sinon c'est faisable à la main, exemple:
    https://github.com/Kitware/CMake/blo...FindALSA.cmake

    Une fois que tu as fait ça tu devrais pouvoir compiler. Et là c'est cool car CLion supporte la toolchains windows, exemple chez moi:



    Tu peux aussi jetter un oeil à vcpkg et regarder mon post un peu enervé sur la gestion de dépendance sous windows plus tôt dans le topic.



    Cette fenêtre que tu vois c'est dans File -> Settings, File -> Settingsc'est là où se trouve TOUT dans CLion, y'a pas besoin de chercher, si tu veux configurer un truc, c'est là.

    La documentation Jetbrains est aussi excellente sur leur site, donc n'hésiter pas à simplement cherche "clion comment faire mon truc" sur google et tu devrais vite trouver.

    -------------

    Une fois que t'arrives à compiler tu pourras t'amuser à rendre ça plus propre, toutes les directives CMake (add executable, etc.) supportent les chemins relatifs et absolus, donc tu pourras te faire ton sous dossier clean si tu le souhaites.

    CLion par défaut n'a besoin que d'un CMakeLists.txt, c'est tout, c'est ça qui constitue un projet. Dans le .idea/ sont stockés des préférences genre comment formatter le code pour ce projet (ce qui peut aussi être fait via clang-format alternativement, hautement configurable on vous dit). Donc à vrai dire y'a jamais AUCUN risque à simplement dégager le .idea/. Sachant que CLion t'offres toujours le choix de stocker les préférences à l'échelle de CLion (system wide) ou à l'échelle du projet (.idea/).

    Par défaut tu vois que mon dossier de build est cmake-build-debug, mais ça aussi tu peux le configurer dans CLion (regarde mon screenshot: build directory) pour aligner sur ce que tu fais. Ce dossier contiendra le make, mais aussi l'exécutable etc.
    C'est l'exact équivalent de faire: mkdir build && cd build && cmake .. && make, en gros

    Si t'as des questions hésite pas mais je pense vraiment que ça vaut la peine de tenter de faire tourner ça avec CLion.

    - - - Mise à jour - - -

    Concernant la compatibilité avec Make, je sais que c'est arrivé récemment, mais je n'ai jamais essayé. Normalement c'est comme le CMakeLists.txt, il faut ouvrir un dossier avec un fichier make viable, mais ouais jamais testé donc je ne sais pas.

    EDIT:

    Ah oui j'oubliais, le plus simple c'est peut-être de démarrer un nouveau projet sous CLion, par défaut t'auras un hello world, comme ça tu verras à quoi ça ressemble.
    La toolchain windows sera trouvée automatiquement par CLion, tu pourras compiler et tester
    Dernière modification par Anonyme20240202 ; 10/06/2021 à 10h01.

  16. #4126
    Wow merci Kamikaze ! Tu gères !
    J'aurai ptet pas la possibilité de tester ça ce soir mais je vais essayer au plus vite. Ptet ce midi au taf, mais la pause d'1h passe vite.


    Effectivement je pourrais partir d'un projet de Hello World et m'inspirer de ce projet + tes instructions très complètes pour arriver à mettre d'aplomb un projet qui analyze, compile, linke, se lance et se débogue via CLion. Ou tenter la méthode auto.
    J'ai à peu près zéro doute que ce sera plus confortable que Netbeans une fois que ce sera d'aplomb.

    Et puis c'est comme pour mes projets VS et NB, une fois que je me suis fait iech' à configurer une arbo et des projets qui vont avec, ça fait une base réutilisable pour d'autres dépôts plus tard.


    S'il suffit d'un cmakelists et c'est tout, ptet pas besoin d'un sous-dossier clproject, faut que j'y réflechisse !
    Merci encore !

  17. #4127
    Je découvre qu'en C++, on ne peut pas écrire :
    Code:
    #include <windows.h>
    
    constexpr HANDLE NullHandle = INVALID_HANDLE_VALUE;
    ou utiliser INVALID_HANDLE_VALUE comme paramètre de template. Merci Windows et son type HANDLE tout pourri. C'est dur d'aimer la programmation système avec Windows (moi, je n'y arrive pas).

  18. #4128
    Mais ouais§ Cwningen qui vient supporter notre assaut contre l'oppression grosoft

  19. #4129
    Tu aimes mettre des -1 dans des pointeurs ?

  20. #4130
    Non

    J'faisais référence au topac https://forum.canardpc.com/threads/9...c-rien-dedans/

    Ou je médis (gentiment) microsoft

    - - - Mise à jour - - -

    Sur linux on a aussi du -1 mais les file descriptor c'est du int au moins pas du pointeur. M'enfin je descend rarement à ce niveau j'utilise une lib crossp de preférence

  21. #4131
    Me rend curieux ton histoire, il font des merdes du genre du coup? Je pige pas leur logique, ça sonne hacky voire plateform dependent?

    #include <iostream>

    int main() {
    // auto object = 0;
    auto my_address = 0x123456789fffffff; // 0xffffffffffffffff invalid
    void* handle = reinterpret_cast<void*>(my_address); // ou genre handle = &object;

    void* invalid_handle = reinterpret_cast<void*>(-1);
    std::cout << (int*)invalid_handle << std::endl;

    if(handle == invalid_handle) {
    std::cout << "invalid" << std::endl;
    } else {
    std::cout << "valid" << std::endl;
    }

    return 0;
    }
    Dernière modification par Anonyme20240202 ; 10/06/2021 à 15h57.

  22. #4132
    En même temps, si c'est de la programmation système ils peuvent se permettre d'être plateforme dépendant

  23. #4133

  24. #4134
    Je pense pas qu'il y ait de problèmes en C, mais en C++, le compilateur est plus strict sur ce qu'on peut assigner à un pointeur dans les expressions constexpr ou en paramètre non-type de template. INVALID_HANDLE_VALUE (un define pour, en gros, (void *)(intptr_t)-1), n'est ni un pointeur valide, ni une constante (parce que ça contient un reinterpret_cast). HANDLE est censé être un type opaque et on ne doit pas te préoccuper de ce qu'il contient. Mais là ça ressort. Tant pis, je laisse tomber ma programmation générique, je ferais du copier-coller.

  25. #4135
    Et en même temps merci de ne pas faire des APIs système en C++ hein.
    Sleeping all day, sitting up all night
    Poncing fags that's all right
    We're on the dole and we're proud of it
    We're ready for 5 More Years

  26. #4136
    Citation Envoyé par Kamikaze Voir le message
    J'pensais au CPU genre 32bit vs 64
    Je dirais : même réponse, à partir du moment ou tu a deux systèmes distincts pour 32bit vs 64bit, et que tu code pour l'un de ces systèmes, tu peux te permettre de ne pas faire de code compatible avec l'autre.

  27. #4137
    Ouais je pensais à des trucs idiots. Perso quand je pense à void pointer je pense à stocker une adresse, dont la taille dépend de ton système, du coup si tu transmets ça via réseau ou autre si t'as des proc connectés et convertit etc. Je sais pas. Mais bref j'imagine que le post de Cwningen résume bien "censé être un type opaque et on ne doit pas te préoccuper de ce qu'il contient"

  28. #4138
    Des news suite aux conseils de Kamikaze et Vectra

    J'ai récupéré CMake mais la GUI semble prévue pour permettre de générer des projets Visual Studio à partir d'une config CMakeLists.
    Voulant faire l'inverse, j'ai cherché à trouver un tool qui automatise ça.
    J'ai chopé un lien sur StackOverflow qui renvoyait vers deux tools, dont un des deux est maintenu, j'ai pas le nom en tête mais ça doit être celui dont parlait Vectra vu que c'était un module Python à récupérer via pip.

    Je lui ai fait manger la solution VS2017 de mon projet de tests (qui contient, elle, le projet appli console de test et le projet lib statique à linker) et il m'a sorti le CMakeLists qui a l'air assez complet.
    Pas encore zieuté dans les détails, j'ai balancé ça dans un dossier "clproject" comme je le souhaitais et CLion me l'a reconnu comme un projet.
    Je l'ai ouvert, il me propose une config Debug de base, je peux lancer le débogage mais il s'est foiré au build, apparemment il n'arrive pas à choper des sources.

    Je regarderai plus en détail en rentrant du taf, doit y avoir des chemins à rectifier ou des includes manquants, j'espère que ce sera rapide à corriger

    Je vous tiens au jus

  29. #4139
    Je conseille fortement de ne pas utiliser de GUI pour CMake, honnêtement. C'est des fichiers à éditer à la main, c'est fait pour. Enfin rien de grave bien sûr, tu peux utiliser la GUI, mais si ça te prend la tête, pas besoin.

    Et ouais, vraiment, essaye le "nouveau projet" avec CLion, ça te fera un Hello World, et tu verras tout sera très clair.

    Aussi CLion inclus CMake par défaut

    - - - Mise à jour - - -

    Files -> Settings -> Build, Execution, Deployment -> Toolchains

    Et tu verras dans CMake, y'a un choix "Bundled"


    ----

    Oui et en plus CLion t'offre la complétion quand tu édites le CMake depuis CLion. Je recommande fortement.
    Dernière modification par Anonyme20240202 ; 11/06/2021 à 13h31.

  30. #4140
    Oui, malheureusement, le cmake generator, il oublie quelques fichiers source des fois.
    Tu les vois dans le fichier principal et il en manque parfois.

    Faut pas lui en vouloir; c'est un projet Python à la base
    Mais les scripts CMake qu'il contient sont de qualitay en général.


    Si tu fais ton projet, autant commencer ton CMake from scratch évidemment.
    Mais quand tu dois te démerder avec une solution dont tu hérites sans savoir comment le projet est fait, cmake-generator aide bien.
    Autant je me démerde toujours avec CMake, autant les solutions visual me laissent circonspect.

Page 138 sur 182 PremièrePremière ... 3888128130131132133134135136137138139140141142143144145146148 ... DernièreDernière

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •