Comment puis-je surmonter la paralysie par analyse lors du codage?

37

Lorsque je commence un nouveau projet, je commence souvent à penser immédiatement aux détails de la mise en œuvre. "Où vais-je placer DataBaseHandler? Comment dois-je l'utiliser? Les classes qui veulent l'utiliser doivent-elles s'étendre à partir d'une superclasse abstraite ..? Devrais-je utiliser une interface? Quel niveau d'abstraction vais-je utiliser dans ma classe qui contient méthodes d'envoi de requêtes et d'analyse de données? "

Je finis par caler pendant un long moment parce que je veux coder pour l'extensibilité et la réutilisabilité. Mais j'estime presque impossible de dépasser la réflexion sur la mise en œuvre parfaite.

Et puis, si j'essaie juste de dire "vissez, faites-le juste!", Je me suis heurté à un mur de briques assez rapidement parce que mon code n'est pas organisé, j'ai mélangé des niveaux d'abstractions, etc.

Quelles sont les techniques / méthodes que vous avez pour vous lancer dans un nouveau projet tout en mettant en place une structure logique / modulaire qui s'adapte bien?

- - EDIT - -

Eh bien, c’est déjà le type de question à laquelle il est difficile d’accepter une réponse, mais je voulais obtenir plus de commentaires, voir s’il ya un consensus. TDD semble vraiment cool et, franchement, je voulais me familiariser davantage avec JUnit, etc. En même temps, que pensent les fans de TDD du fait qu’un point légitime en rapport avec la résolution de TDD problèmes particuliers, c’est que le TDD ne semble pas vraiment aborder la question du design. Bien sûr, je conviens que TDD m'aidera à définir ce que je veux faire et que je pourrai ensuite analyser le comment, mais il existe de nombreux modèles / structures de conception globale qui pourraient tous passer par les tests unitaires. C'est juste ça: il teste des unités simples. Je suppose que je suis un peu confus ... Je ne sais pas. Peut-être que je'

Merci!

Mode de luxe
la source
2
Reculez, prenez un stylo et du papier, dessinez la vue d'ensemble. cela vous aidera ensuite à concevoir la mise en œuvre de manière plus structurée plutôt que de vous perdre dans les détails ...
Darknight
c'est une excellente question. C’est un piège dans lequel je me suis rendu coupable.
Corv1nus

Réponses:

16

Je recommande l'utilisation de Test-Driven-Development , il faut s'y habituer surtout quand on travaille avec un bon IDE comme eclipse, mais les avantages sont énormes.

Essentiellement, vous écrivez les tests dans votre code avant d’écrire le code lui-même. Vous êtes donc obligé de regarder votre code du point de vue de la façon dont il sera utilisé, ce qui signifie que vos interfaces évoluent au fur et à mesure que vous implémentez des scénarios.

Une autre caractéristique est que vous implémentez de très petits morceaux (plus ils grandissent, plus vous êtes expérimenté dans la technique et la programmation), ce qui vous oblige à vous concentrer à chaque fois sur un problème très petit et bien défini.

Et également depuis que vous écrivez un test et que vous ne l'implémentez qu'ensuite, vous avez devant vous un test qui échoue. Donc, si vous êtes comme la plupart des programmeurs, vous ne vous laisserez pas aller à une analyse loufoque, car vous penserez: "Je dois faire en sorte que ce test fonctionne".

Un petit exemple java:
Disons que je veux développer un programme qui lit et écrit un message à partir d’une base de données.

Je commence donc par la première action bien définie, il me faut un DB:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
}

ok, donc ici je vois que je dois implémenter la classe DbConnector.getDB pour qu'elle retourne la base de données, jusqu'à ce que ce test échoue. Je vais faire ça ...

Non j'ajoute la prochaine chose que je veux faire, chargez le message de la base de données:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
}

Maintenant, j'ai ajouté une autre petite fonctionnalité à la base de données qui consiste à récupérer un message. Je vais l'implémenter. Une fois terminé, je continue à parcourir une fonctionnalité à la fois jusqu'à atteindre quelque chose comme ceci:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
  message = "foo bar";
  db.storeMessage(message);
  message = db.fetchMessage();
  assertEquals("foo bar", message);
}

Cela peut sembler un exemple très simple, mais cela fonctionne également pour des tâches plus complexes. Je sais que cela prend beaucoup de temps au début, mais au fur et à mesure que vous vous y habituez, vous constatez que c’est beaucoup plus efficace. Pour l’un, vous évitez la paralysie par analyse et pour l’autre, vous obtenez un code beaucoup plus robuste, qui contient généralement moins de bogues et passe moins d’itérations.

Asaf
la source
4
Et TDD vous oblige beaucoup à refactoriser, de sorte que vous entrez dans un mode de travail continu de refactorisation qui vous aidera à percer le mur de briques du code gâché, comme le fait le programme programmers.stackexchange.com/questions/86364/… .
grincer des dents
En fait, j’estime que le premier aspect du test TDD est un obstacle dans ce genre de situation. Si j'ai suffisamment de difficulté à concevoir l'interface elle-même, en quoi la conception des tests sera-t-elle plus facile ou plus évidente? Cela et le fardeau de refactorisation au tout début d’essayer de concevoir quelque chose sont beaucoup trop lourds. Je me demande comment les autres traitent avec cela.
Steven Evers
1
@SnOrfus, à droite. TDD fonctionne bien lorsque vous avez vos modules et que vous souhaitez vous concentrer sur quoi et comment. Mais ces modules peuvent être organisés de différentes manières. La façon dont ils sont regroupés, le type de structure que vous allez utiliser ne sont pas vraiment clarifiés par le TDD.
LuxuryMode
5
Hmmmm, cela ressemble à un fan de TDD ..... Qu'est-il déjà arrivé d'utiliser un stylo et du papier pour dessiner une architecture? ou suis-je à l'ancienne mode et pas assez "branché" ...
Darknight le
1
Le stylo et le papier (ou le tableau blanc) sont bons. Esquisser le plan d'ensemble, la grande image. Si cela ne tient pas sur un bout de papier, c'est trop compliqué. Une fois que vous avez un plan détaillé, vous pouvez vous mettre à jouer à BDD, à vous moquer, etc.
Donal Fellows
10

Cela m’arrive, j’ai donc pris l’habitude d’accepter (et d’embrasser) un état d’esprit de refactorisation continuelle. Je fais la chose la plus simple qui puisse fonctionner, puis je la nettoie, l’organise, la découpler, la tester et passer à autre chose.

Cela ne veut pas dire qu'il n'y a pas beaucoup de planification, mais cela se produit très rapidement et plus souvent que des gribouillis à la ferraille ou dans ma tête. Dans l’ensemble, j’appelle parfois ce petit processus des micro-itérations car elles prennent entre 5 et 20 minutes chacune et, d’expérience, il en faut 2-3 pour terminer ce que je travaille (selon ce que je fais, bien entendu).

En note de bas de page: j'ai enseigné à un certain nombre de personnes différentes formes d'écriture (rapports, essais et rédaction technique en général) et c'est comme cela que je les oblige à écrire pour surmonter le blocage de l'écrivain. «Laissez simplement de côté tout ce qui vous passe par la tête sur votre page. Ensuite, nous allons en comprendre le sens en séparant le tout en paragraphes et en vérifiant le déroulement. Au besoin, nous le réécrirons même.

Steven Evers
la source
1
+1 pour avoir mentionné l'écriture. J'ai récemment adopté l'approche de refactorisation fréquente du codage et je l'ai appliquée à l'écriture; fonctionne très bien pour moi.
Zsolt Török
2

Quelques choses qui pourraient fonctionner:

  • Identifiez le problème central que vous essayez de résoudre - quel est le cœur même de ce que vous voulez faire? Implémentez simplement cela, et le strict minimum de code de support pour le faire fonctionner. Une fois que cela fonctionne à votre satisfaction, construisez de manière itérative, refactoring sans pitié à chaque étape.
  • Voyez si d'autres paradigmes de programmation fonctionnent pour vous. Malgré tous ses mérites, la programmation orientée objet n'est pas la solution à tous les problèmes, et le cerveau de tous les programmeurs ne fonctionne pas ainsi. Choisissez un langage fonctionnel (pur); écrire du code de procédure; plonger jusqu'au niveau du matériel et faire un peu de C ou peut-être même un assembleur; etc. Quelques langues qui pourraient vous secouer la tête (en supposant que vous utilisez actuellement quelque chose comme C ++ / Java / C # / VB / ...): Haskell, ML, Lisp (plusieurs dialectes parmi lesquels choisir), Erlang, Prolog, Smalltalk, Javascript (si vous n'essayez pas de le faire se comporter comme Java et d'embrasser sa nature de fermeture à la place), C, Pascal, awk et probablement une douzaine de plus. La principale caractéristique est qu’ils doivent être très différents de ce que vous utilisez maintenant. Ce n'est pas quelque chose que vous voulez faire sur un grand projet avec beaucoup en jeu,
  • Utilisez une méthode de conception radicalement différente. Voyez si vous pouvez prendre la conception d'un angle différent. Je suppose que vous commencez habituellement à concevoir en organisant vos cours; que diriez-vous de commencer avec des structures de données pour un changement? Ou que diriez-vous de concevoir l'interface utilisateur en premier, de dessiner littéralement des formulaires de saisie avant de concevoir une fonctionnalité?
tdammers
la source
1

Pour de nombreuses décisions de conception, il peut être utile de créer un "pic", qui est un effort de recherche court et limité dans le temps, où vous pouvez explorer certaines options d'architecture ou de conception en codant pour un prototype jetable. Par exemple, vous pouvez explorer l'utilisation d'une bibliothèque open source ou la manière dont vous allez organiser vos classes et interfaces. L’essentiel est de rester concis afin de pouvoir essayer une autre approche si la première n’est pas satisfaisante et, espérons-le, acquérir suffisamment de connaissances dans le cadre de l’exercice pour mieux prendre les décisions architecturales ou prouver le concept. L’exercice lui-même implique un codage immédiat qui permet de sortir du "bloc des écrivains" sans nécessairement s’engager trop tôt pour le "géniteur".

Après cela, il est avantageux d'utiliser l'approche TDD ou BDD mentionnée par Asaf pour poursuivre la mise en œuvre du projet.

Clé en main
la source
+1 je suis d'accord. Prévoyez de jeter la première tentative. Traitez-le comme une expérience d'apprentissage. J'en ai jeté pas moins de six, avant que je pense que je veux rester avec le septième.
Mike Dunlavey
1

Yagni , donc ne pense pas trop au début.

Investissez plus de temps pour définir, comprendre l'objectif et le problème.

"Extensibilité et réutilisabilité" est le résultat naturel du cycle de vie de logiciels bien écrits.

9dan
la source
0

Je suppose que nous envisageons un projet de taille moyenne.
Je commencerais par aller sur la planche à dessin. Vous devez avoir vos exigences fonctionnelles et non fonctionnelles prêtes avant de le faire. Vous devez d’abord concevoir l’architecture logicielle, c’est-à-dire examiner tous les modèles architecturaux qui répondent à vos besoins.
Une fois que vous avez décidé de l’architecture de votre architecture, vous devez entrer dans la conception de bas niveau, c’est-à-dire examiner toutes les entités, classes et fonctionnalités. . Ici, vous allez à nouveau essayer d’identifier les modèles de conception qui s’intègrent. Dans le processus, vous saurez quelles sont vos classes de base et les interfaces dont vous auriez besoin.
Vous pouvez ensuite construire le cadre et exécuter quelques tests rapides pour voir si satisfait toutes vos exigences non fonctionnelles
J'irais ensuite avec Test Driven Development comme @Asaf l'a suggéré.

N'oubliez pas que, malgré le temps consacré à la conception et à l'architecture, soyez toujours disposé à revoir l'architecture si besoin est.

hangar 18
la source
0

Je pense que c'est une excellente question et que rien ne fonctionnera pour tout le monde. Je pense effectivement qu'une telle paralysie est un sous-produit naturel de devenir de plus en plus compétent dans votre domaine. Cela dit, voici quelques solutions que j'apporte mais qui ne résolvent pas le problème:

  • Mettez votre projet vierge de côté et travaillez sur la version fugly. Ceci est la version où vous vous dites: a. Le code n'est pas censé être joli. En fait, dites-vous qu'une refactorisation et un reformatage majeurs ne sont pas autorisés. Laissez-le être absolument désorganisé et libérez-vous des liens de bon codage. b. Il faut que ça fonctionne. c. Ce que je découvre au sujet de l’espace des problèmes m’étonne toujours lorsque j’évoque toutes les autres préoccupations. Je me retrouve également avec des petites choses qui m'aident souvent à concevoir le bon design de manière plus éclairée.

  • Mettez de côté un bloc de taille décente où vous êtes sur le projet, juste sans ordinateur. Essayez de conceptualiser ce que vous essayez vraiment d'accomplir et recherchez ce zen magique qui transcende la folie OO / Design Pattern.

Kevin Hsu
la source
0

Donnez une expression concrète à vos pensées: écrivez / tapez-les, dessinez-les ou autre chose. Cela vous aidera à revoir vos pensées au besoin. cela vous empêchera de tourner en rond; vous aide à penser plus clairement.

Chaque fois que je me vois aller nulle part et partout pensant à quelque chose, je les tape et cela m'aide à penser clairement.

Srisa
la source
0

Je commence généralement par le début, crée le prototype le plus simple possible et lance quelque chose. Utilisez le prototype pour procéder au reverse engineering des scénarios de test Happy Path, des scénarios de test pour piloter les interfaces, puis réfléchissez aux contrats pré / post afin de vous aider à établir une couverture de test.

Ne vous préoccupez pas de l'abstraction, de l'optimisation ou de la vérification jusqu'à ce que le problème soit entièrement compris.

Sbrenton
la source