Design patterns et best practices

2»

Réponses

  • Par définition oui


  • Finalement, on en utilise sans arrêt. On est bien d'accord.


     


    Je ne comprend donc pas pourquoi une telle discussion (à  laquelle je n'ai rien compris) sur le singleton... Oups


  • Pourrais-tu repréciser ton niveau de connaissance en POO?


     


    Il faut bien faire attention au fait que lorsque tu instancies un objet tu créé "un nouvel espace mémoire" dédié à  cet instance d'objet ce qui est différent d'avoir un singleton.


  • colas_colas_ Membre
    mars 2015 modifié #35

    Non :


     


     


    -> refactoring c'est des changements dans ton code (fusion de deux classes, suppression de passages inutiles, création de nouvelles sous-classes, etc.) qui ne modifient pas le comportement de ton programme et qui améliore sa lisibilité et sa maintenabilité.


     


    -> singleton : quand tu dis "On en utilise partout", donne des exemples ! Les exemples que tu as donné sont faux, ce ne sont pas de singletons.


     


    EDIT :


     


    Une classe a vocation à  créer des objets. Exemple, la classe Car peut créer des objets de type Car, et cette classe peut en créer plein, à  l'aide du code [[Car alloc] init].


     


    Un singleton (ou shared instance, ce sont des concepts presqu'équivalents) c'est une classe qui durant toute la vie du programme ne créera au plus que un objet !!! Et on peut y accéder via une méthode de class. Exemple, j'ai une classe dont mon projet qui s'appelle DataManager. Je n'ai pas besoin d'avoir 10000 data managers dans mon programme. Un seul, aisément accessible, permettra de me donner les infos dont j'ai besoin. Donc, j'ai fait en sorte que cette classe soit un singleton et je n'utilise pas [[DataManager alloc] init] mais [DataManager  sharedDataManager] qui me renvoie toujours le même objet.


  • CéroceCéroce Membre, Modérateur

    Finalement, on en utilise sans arrêt. On est bien d'accord.

    Ben non... On l'utilise dans des cas exceptionnels, justement.

    Je ne comprend donc pas pourquoi une telle discussion (à  laquelle je n'ai rien compris) sur le singleton... Ou

    Singleton: instance unique, à  tout moment d'une classe.
    Bon exemple: UIDevice, qui permet d'avoir des infos sur l'iPhone/iPad.
  • Le refactoring ça sert à  diminuer la productivité de l'équipe !!


    Je m'explique ...


    ça sert à  éliminer les duplications de code, les séquences de code qui se ressemblent, etc. Comme de la factorisation en mathématiques. Par exemple si j'ai la même séquence de code "C" dans la méthode "A" et dans la méthode "B", on va écrire une méthode privée qui contiendra le code "C" qui sera appelée par les méthodes A et B.


    Le refactoring diminue les coûts de maintenance car s'il y a un défaut à  corriger dans la séquence de code "C", il vaut mieux que ce code soit centralisé dans une méthode. La correction ne sera faite qu'une fois, on ne risquera plus d'oublier de faire la même correction partout ou le code était dupliqué.


    C'est aussi à  l'occasion du refactoring qu'apparaissent souvent les Design Patterns dans les méthodes de "conception émergente" comme le TDD.


    Pourquoi ça sert à  diminuer la productivité de l'équipe ? Parce que ce travail consiste à  diminuer le nombre de lignes de code. Ce qui était mal vu à  une époque pas si lointaine où la productivité était mesurée en nombre de lignes de code produites par jour.


     


    Un Singleton ce n'est pas une instance unique d'une classe.


    C'est une classe qui ne peut être instanciée qu'une fois.


    Dans ton exemple



    var myLineView: LineView!
    var myRoundDView: RoundView!
    var myRoundGView: RoundView!

    Si RoundView était un singleton, myRoundDView et myRoundGView référenceraient tous les deux la même instance unique de la classe.


     

    Cela dit, je ne sais pas si Swift permet de créer de vrais Singletons.

    En Objective-C ce n'est pas si simple, la pratique courante consiste à  créer une méthode de classe "shared..." qui va retourner une instance partager, mais il est toujours possible de créer d'autres instances de cette classe. Le nom de Singleton me paraà®t usurpé pour ce pattern Objective-C, j'aurais plutôt tendance à  appeler ça un Shareton.



  •  


    -> refactoring c'est des changements dans ton code (fusion de deux classes, suppression de passages inutiles, création de nouvelles sous-classes, etc.) qui ne modifient pas le comportement de ton programme et qui améliore sa lisibilité et sa maintenabilité.


     




     


    Effectivement c'est ça du refactoring. Néanmoins, je pense que busterTheo parlait du refactoring (changement de nom) des variables. 


    C'est donc pour cela que je parlais de "ce type" de refactoring.

  • Oulaaaaaah,


    merci pour toutes vos explications. J'avoue que je n'ai pas tout compris, mais quand même une partie.


     


    En tout cas, j'adore :



     


    Un Singleton ce n'est pas une instance unique d'une classe.


    C'est une classe qui ne peut être instanciée qu'une fois



    ça, c'est super clair.


     


    Merci à  vous...


  • Joanna CarterJoanna Carter Membre, Modérateur
    mars 2015 modifié #40


    En Objective-C ce n'est pas si simple, la pratique courante consiste à  créer une méthode de classe "shared..." qui va retourner une instance partager, mais il est toujours possible de créer d'autres instances de cette classe. Le nom de Singleton me paraà®t usurpé pour ce pattern Objective-C, j'aurais plutôt tendance à  appeler ça un Shareton.




     


    Pardonnes-moi mais c'est pas le cas si l'on écrivais la classe correctement :



    @interface Classe

    + (instancetype)sharedInstance;

    @end


    @implementation Classe

    //

    #pragma mark - Singleton implementations

    + (instancetype)sharedInstance
    {
    static Classe *instance;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^
    {
    instance = [[super allocWithZone:nil] init];
    });

    return instance;
    }

    + (id)allocWithZone:(NSZone *)zone
    {
    return [self sharedInstance];
    }

    - (id)copyWithZone:(NSZone *)zone
    {
    return self;
    }

    @end

    Même si l'on appelait [[Classe alloc] init] ou [monInstance copy], ça renverrait la même instance que [Classe sharedInstance]


  • et en swift, comment tu ferais un vrai singleton


  • AliGatorAliGator Membre, Modérateur
    mars 2015 modifié #42
    Avec un failable initializer qui fail a chaque fois sauf lors de la création du singleton peut-être ?


    Bon ça ne créerait pas une classe qui "retourne toujours la même instance à  chaque appel au constructeur" mais plutôt une classe qui "ne peut pas retourner d'instance autrement qu'en passant par la sharedInstance", mais c'est déjà  une piste.
  • Joanna CarterJoanna Carter Membre, Modérateur

    Vous voulez un Singleton en Swift ? Voila !



    class Classe
    {
    static let sharedInstance: Classe = Classe()

    private init() {}
    }

    L'astuce est de redéfinir l'init comme privé ; du coup il n'est pas possible d'instancier la classe sauf par le let sharedInstance  8--)


  • Il n'est pas plus intéresser de laisser l'opportunité de pouvoir instancier la classe? 


    Donc avoir les deux, la méthode d'init et le sharedInstance?


  • zoczoc Membre
    mars 2015 modifié #45

     Joanna, mais swift 1.2 minimum requis pour les constantes statiques dans les classes.


     


    Elles sont par contre autorisées dans les structs.


     


    Pour swift 1.0 :



    class Singleton {
    class var sharedInstance: Singleton {
    struct Static {
    static let instance: Singleton = Singleton()
    }
    return Static.instance
    }
    }


  • Joanna CarterJoanna Carter Membre, Modérateur

    @NSMaxime - pas du tout. Le but d'un Singleton est que l'on ne puisse jamais avoir plus d'une instance. En Objective-C, c'est possible de laisser accessible l'init parce que l'on puisse redéfinir la méthode allocWithZone mais, en Swift, on n'a pas le choix.


     


    @zoc - tout à  fait. Autrement, il faut utiliser un "nested struct" pour l'instance




  • Pardonnes-moi mais c'est pas le cas si l'on écrivais la classe correctement :



    @interface Classe

    + (instancetype)sharedInstance;

    @end


    @implementation Classe

    //

    #pragma mark - Singleton implementations

    + (instancetype)sharedInstance
    {
    static Classe *instance;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^
    {
    instance = [[super allocWithZone:nil] init];
    });

    return instance;
    }

    + (id)allocWithZone:(NSZone *)zone
    {
    return [self sharedInstance];
    }

    - (id)copyWithZone:(NSZone *)zone
    {
    return self;
    }

    @end

    Même si l'on appelait [[Classe alloc] init] ou [monInstance copy], ça renverrait la même instance que [Classe sharedInstance]




     


    Bon j'avoue, je dois avoir le cerveau qui ramollit.


    Je ne comprends absolument pas ta solution Joanna. Pour moi ça fait simplement un deadlock sauf si le premier appel de la classe est sur sharedInstance.


    Si le premier appel est sur allocWithZone, ça appelle sharedInstance, qui appelle allocWithZone qui appelle sharedInstance et là  ça bloque sur le dispatch_once.

  • AliGatorAliGator Membre, Modérateur
    @jpimbert non si le premier appel est sur allocWithZone, ça appelle sharedInstance... qui appelle le allocWithZone... de "super", donc de la classe parente ! Donc ça boucle pas ;)
  • Ah ! OK !


    J'ai donc bien le cerveau ramollit.


     


    Mais j'aime pas !


     


    Pour faire des trucs comme ça, il faut savoir que la taille mémoire allouée par allocWithZone est la même quelle que soit la classe de l'instance créée. Moi bêtement je pensais que ça dépendait au minimum du nombre et de la taille des variables d'instance.


    ça heurte mes bonnes pratiques de la conception objet d'utiliser des connaissances sur le fonctionnement interne d'une méthode.


     


    Question subsidiaire, pourquoi on continue à  utiliser allocWithZone, et pas simplement alloc.


  • jpimbertjpimbert Membre
    mars 2015 modifié #51

    N'insistez pas, je comprends de moins en moins ...


    Dans le post donné par Joanna, il est question de boucle infinie.


    Je ne comprends ce qu'est super dans une méthode de classe.


     


    Et pourtant ça marche



    - (void)testExample {
    Classe *c1 = [[Classe alloc] init];
    Classe *c2 = [[Classe alloc] init];
    XCTAssertEqualObjects(c1, c2, @Les deux variables doivent référencer la même instance);
    c1.name = @Test Name;
    XCTAssertEqualObjects(@Test Name, c2.name, @Le nom de c2 doit être celui de c1);
    }

Connectez-vous ou Inscrivez-vous pour répondre.