Como supero a paralisia por análise ao codificar?


37

Quando inicio um novo projeto, muitas vezes começo imediatamente a pensar nos detalhes da implementação. "Onde vou colocar o DataBaseHandler? Como devo usá-lo? As classes que desejam usá-lo estendem-se a partir de uma superclasse Abstract ...? Devo usar uma interface? Que nível de abstração vou usar na minha classe que contém métodos para enviar solicitações e analisar dados? "

Acabo parando por um longo tempo porque quero codificar a extensibilidade e a reutilização. Mas acho quase impossível deixar de pensar em como implementar perfeitamente.

E então, se eu tentar apenas dizer "dane-se, basta fazê-lo!", Bati rapidamente em uma parede de tijolos porque meu código não está organizado, misturei níveis de abstração etc.

Quais são algumas técnicas / métodos que você tem para iniciar um novo projeto enquanto também configura uma estrutura lógica / modular que será bem dimensionada?

- - EDITAR - -

Bem, esse já é o tipo de pergunta difícil de ser respondida, mas queria obter mais feedback, veja se há algum consenso. O TDD parece muito legal e, francamente, eu pretendo acelerar o uso do JUnit, etc. Ao mesmo tempo, o que os fãs do TDD pensam sobre o fato de que um ponto legítimo em relação ao TDD é a solução? questões particulares, é que o TDD não parece realmente abordar a questão do design. Certamente, eu concordo que o TDD me ajudará a definir o que eu quero fazer e, em seguida, poderei trabalhar gradualmente no how, mas existem muitos padrões / estruturas gerais de design diferentes que podem passar pelo teste de unidade. É isso mesmo: ele testa UNIDADES únicas. Acho que estou um pouco confuso ... não sei. Talvez eu'

Obrigado!


2
Dê um passo atrás, pegue uma caneta e papel, desenhe a foto maior. isto irá ajudá-lo, em seguida, projetar a implementação de uma forma mais estruturada, em vez de perder o seu auto nos detalhes ...
Darknight

Esta é uma grande pergunta. Esta é uma armadilha na qual também fui culpada de cair.
Corv1nus

Respostas:


16

Eu recomendo usar o Test-Driven-Development , é preciso algum tempo para me acostumar, especialmente quando se trabalha com um bom IDE como o eclipse, mas as vantagens são grandes.

Basicamente, o que você faz é escrever os testes no seu código antes de escrever o próprio código. Portanto, você é forçado a analisar seu código do ponto de vista de como ele será usado, o que significa que suas interfaces evoluem à medida que os cenários são implementados.

Outra característica é que você implementa em pedaços muito pequenos (eles aumentam quanto mais experiente você é na técnica e na programação), o que força você a se concentrar em um problema muito pequeno e bem definido a cada vez.

E também, desde que você primeiro escreveu um teste e só depois o implementou, você tem um teste com falha à sua frente. Portanto, se você é como a maioria dos programadores, não se deixa levar por análises malucas porque pensa: "Preciso fazer esse teste funcionar".

Um pequeno exemplo de java:
digamos que eu queira desenvolver um programa que leia e grave uma mensagem de um banco de dados.

Então, eu começo com a primeira ação bem definida, preciso de um banco de dados:

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

ok, então aqui vejo que preciso implementar a classe DbConnector.getDB para que ele retorne o banco de dados, até então esse teste falha. Eu vou fazer isso ...

Não adiciono a próxima coisa que quero fazer, carregue a mensagem do banco de dados:

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

Agora, adicionei outro pequeno recurso ao banco de dados que é buscar uma mensagem. Implemento isso. Depois de concluído, continuo com um recurso de cada vez até chegar a algo assim:

@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);
}

Pode parecer um exemplo muito simples, mas isso também funciona para tarefas mais complexas. Sei que consome muito tempo a princípio, mas quando você se acostuma, percebe que, na verdade, é muito mais eficiente. Por um lado, você evita a paralisia por análise e, por outro, obtém um código muito mais robusto, que geralmente possui menos bugs e passa por menos iterações.


4
E o TDD obriga a refatorar muito, de modo que você está entrando no modo de trabalho de refatoração contínua, o que ajudará a romper a parede de tijolos do código incorreto, como mencionado em programmers.stackexchange.com/questions/86364/… .
cringe

Na verdade, acho que o aspecto do primeiro teste do TDD é um obstáculo nesses tipos de circunstâncias. Se estou tendo problemas suficientes para projetar a própria interface, como será mais fácil ou mais óbvio projetar os testes? Isso e o fardo do refator no começo da tentativa de projetar algo são altos demais. Eu me pergunto como os outros lidam com isso.
Steven Evers

11
@SnOrfus, certo. O TDD funciona bem quando você tem seus módulos e deseja se concentrar no que versus como. Mas esses módulos podem ser organizados de várias maneiras. Como eles estão agrupados, que tipo de estrutura você usará não está sendo realmente esclarecido pelo TDD.
LuxuryMode

5
Hmmmm, isso soa como um fanboy do TDD ..... O que aconteceu com o uso de caneta e papel para esboçar uma arquitetura? ou estou moda antiga e não o suficiente "hip" ....
Darknight

11
Caneta e papel (ou quadro branco) são bons. Esboce o plano geral, o quadro geral. Se não couber em um pedaço de papel, é muito complicado. Depois de ter o plano geral, você pode se ocupar com BDD, zombaria etc.
Donal Fellows

10

Isso acontece comigo, então eu adquiri o hábito de aceitar (e abraçar) uma mentalidade de refatoração contínua. Faço a coisa mais simples que poderia funcionar, depois limpo, organizo, desacopro, testo e continuo.

Isso não quer dizer que não haja muito planejamento em andamento, mas acontece muito rapidamente e com mais frequência como rabiscos em pedaços ou na minha cabeça. No geral, às vezes eu chamo esse pequeno processo de micro-iteração, porque eles levam de 5 a 20 minutos cada e, por experiência, leva de 2 a 3 para terminar o que estou trabalhando (dependendo do que estou fazendo, obviamente).

Como uma observação lateral: eu ensinei várias pessoas em diferentes formas de escrita (relatórios, ensaios e redação técnica em geral) e é da mesma maneira que eu as faço escrever coisas para superar o bloqueio de escritor. "Apenas deixe escapar algo sobre o assunto que vier à mente na página. Então, faremos sentido, separaremos tudo em parágrafos e verificaremos o fluxo. Se necessário, vamos reescrevê-lo".


11
+1 por mencionar a escrita. Recentemente, adotei a abordagem de refatoração frequente da codificação e a apliquei na escrita; Funciona muito bem para mim.
Zsolt Török

2

Algumas coisas que podem funcionar:

  • Identifique o principal problema que você está tentando resolver - qual é o cerne da coisa que você deseja fazer? Implemente exatamente isso e o mínimo necessário de código de suporte para executá-lo. Quando funcionar de acordo com a sua satisfação, construa iterativamente, refatorando sem piedade a cada passo.
  • Veja se outros paradigmas de programação funcionam para você. Apesar de todos os seus méritos, a programação orientada a objetos não é a resposta para todos os problemas, e nem todos os cérebros dos programadores funcionam dessa maneira. Escolha uma linguagem funcional (pura); escreva algum código processual; mergulhe no nível do hardware e faça um C ou talvez até um montador; etc. Algumas linguagens que podem agitar sua mente (supondo que você esteja usando algo como C ++ / Java / C # / VB / ...): Haskell, ML, Lisp (vários dialetos para escolher), Erlang, Prolog, Smalltalk, Javascript (se você deixar de tentar fazê-lo se comportar como Java e adotar sua natureza de fechamento), C, Pascal, awk e provavelmente uma dúzia a mais. O principal recurso é que eles precisam ser muito diferentes do que você usa agora. Isso não é algo que você deseja fazer em um grande projeto com muita coisa em jogo,
  • Use um método de design radicalmente diferente. Veja se você pode pegar o design de um ângulo diferente. Suponho que você geralmente comece a projetar organizando suas aulas; que tal começar com estruturas de dados para uma mudança? Ou você projeta a interface do usuário primeiro, literalmente desenhando formulários de entrada antes de projetar qualquer funcionalidade?

1

Para muitas decisões de design, pode ajudar a fazer um "pico", que é um esforço de pesquisa curto e com tempo limitado, no qual você pode explorar algumas opções de arquitetura ou design, codificando para um protótipo descartável. Por exemplo, você pode explorar o uso de alguma biblioteca de código aberto ou como você organizará suas classes e interfaces. A chave é mantê-lo curto para que você possa tentar outra abordagem se a primeira não for satisfatória e, com sorte, você ganhará conhecimento suficiente no exercício para tomar melhores decisões de arquitetura ou provar o conceito. O exercício propriamente dito envolve codificação imediata, o que ajuda a sair do "bloco dos escritores" sem necessariamente se comprometer com o "dar pronto" muito cedo.

Depois disso, é benéfico usar a abordagem TDD ou BDD que Asaf mencionou para avançar com a implementação do projeto.


+1 eu concordo. Planeje jogar fora a primeira tentativa. Trate-o como uma experiência de aprendizado. Já joguei fora seis, antes de pensar em ficar com a sétima.
Mike Dunlavey

1

Você não vai precisar , então não pense muito no começo.

Invista mais tempo para definir, entender o objetivo e o problema.

"Extensibilidade e reutilização" é o resultado natural do ciclo de vida de programas de software bem escritos.


0

Suponho que estamos analisando um projeto de tamanho médio.
Eu começaria indo na prancheta. Você deve ter seus requisitos funcionais e não funcionais prontos antes de fazer isso. Você primeiro criaria a arquitetura do software, ou seja, examinaria todos os padrões de arquitetura que atendam aos seus requisitos.
Depois de decidir como a sua arquitetura se parece, você deve entrar no design de baixo nível, ver todas as entidades, classes e funcionalidades . Aqui, você novamente tentará identificar os padrões de design que se encaixam. No processo, você saberá quais são as suas classes base e as interfaces necessárias.
Você poderá criar a estrutura e executar alguns testes rápidos para verificar se isso satisfaz todos os seus requisitos não funcionais
Eu iria então com o Test Driven Development como o @Asaf sugeriu.

Lembre-se, apesar de gastar um bom tempo em design e arquitetura, esteja sempre disposto a revisitar a arquitetura, se necessário.


0

Eu acho que essa é uma ótima pergunta e nada funcionará para todos. Eu acho que essa paralisia é um subproduto natural de se tornar cada vez mais competente em seu campo. Dito isto, aqui estão algumas coisas que eu ajudo, mas não resolve o problema:

  • Coloque seu projeto original de lado e trabalhe na versão fugaz. Esta é a versão em que você diz a si mesmo: a. O código não deveria ser bonito. De fato, diga a si mesmo que grandes refatorações e reformatações não são permitidas. Seja absolutamente desorganizado e liberte-se dos vínculos da boa codificação. b. Apenas tem que funcionar. c. É sempre surpreendente para mim o que aprendi sobre o espaço problemático quando expulso todas as outras preocupações. Também acabo com pequenos detalhes que geralmente me ajudam a obter o design certo de uma maneira mais esclarecida.

  • Separe um período de tamanho decente em que você estiver no projeto, apenas sem um computador. Tente conceituar o que realmente está tentando realizar e procure aquele zen mágico que transcende a loucura OO / Design Pattern.


0

Dê uma expressão concreta aos seus pensamentos: escreva / digite-os, desenhe-os ou o que for. Isso o ajudará a revisitar seus pensamentos quando necessário; impedirá você de andar em círculos; ajuda você a pensar com mais clareza.

Sempre que me vejo indo a lugar algum e a qualquer lugar pensando em alguma coisa, eu as digito e isso me ajuda a pensar com clareza.


0

Normalmente começo do zero, crio o protótipo mais simples possível e coloco algo em execução. Use o protótipo para fazer a engenharia reversa dos casos de teste do caminho feliz, os casos de teste para conduzir as interfaces e, em seguida, pense nos contratos pré / pós para ajudar a construir a cobertura do teste.

Não se preocupe com abstração, otimização ou verificação até que o problema seja totalmente compreendido.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.