Dijkstra pretendia modularizar o código quando escreveu sobre a separação de preocupações?


9

Primeiro, li um trecho do artigo de Edsger W. Dijkstra, de 1974, "Sobre o papel do pensamento científico":

Deixe-me tentar explicar a você, o que, para mim, é característico de todo pensamento inteligente. É que alguém está disposto a estudar em profundidade um aspecto do assunto de forma isolada por uma questão de consistência própria, sabendo o tempo todo que está se ocupando apenas com um dos aspectos. Sabemos que um programa deve estar correto e podemos estudá-lo apenas desse ponto de vista; também sabemos que deve ser eficiente e podemos estudá-la em outro dia, por assim dizer. De outro modo, podemos nos perguntar se, e se sim: por que, o programa é desejável. Mas nada é ganho - pelo contrário! - abordando esses vários aspectos simultaneamente. É o que às vezes chamei de "separação de preocupações" que, mesmo que não seja perfeitamente possível, ainda é a única técnica disponível para ordenar efetivamente os pensamentos, que eu conheço. É isso que quero dizer com "focar a atenção de alguém em algum aspecto": não significa ignorar os outros aspectos, é apenas fazer justiça ao fato de que, do ponto de vista desse aspecto, o outro é irrelevante. Ele está sendo focado em uma e várias faixas simultaneamente.

Eu vejo a separação moderna de preocupações falar sobre modularizar seu código. No entanto, ao ler a citação acima, entendo isso como focando sua mente em uma tarefa específica de cada vez, sem focar em outros aspectos. Isso não significa para mim necessariamente que o código precisa ser separado em blocos modulares.

Ou seja, digamos que exista um código à sua frente que em um arquivo tenha os conceitos de exibição, repositório, controlador, manipulação de eventos, fábrica etc. tudo em um arquivo.

Para um breve exemplo, aqui está um código que possui acesso a dados e visão (saída):

$sql = "SELECT * FROM product WHERE id = " . db_input($id);
$row = db_fetch_array(db_query($sql)); 
<option value="<?=$row['id']?>"<?= $row['ver'] == $row['ver'] ? '  selected="selected"' : '' ?>>Version <?=$row['ver']?></option>

Usando o OO moderno, eu poderia colocar o acesso a dados em seu próprio arquivo usando o padrão Repository, o código View pode entrar em seu próprio modelo de arquivo, e eu posso conectá-los para se comunicar através de um controlador (ou Action ou Request Handler), e posso adicione uma fábrica para criar e conectar várias dependências. E eu posso ter um arquivo de configuração que define essas fábricas. Certamente, está a um passo de tudo em um único arquivo.

Minha pergunta sobre a separação de preocupações é a seguinte: lendo a citação de Dijkstra, tive uma idéia de que talvez ele não quisesse necessariamente que a separação de preocupações fosse "separação modular de código (em arquivos ou em suas próprias funções / métodos / etc)", e que ele pretendia mais focar a mente em um aspecto do programa, sem sobrecarregar-se com o foco em outros aspectos importantes, ainda que não sejam considerados atualmente, independentemente de serem fisicamente separados em código ou não.

Por que, então, estamos nos sobrecarregando com separação física de código modular e padrões de design? Não será suficiente focar-se apenas em um aspecto, independentemente de como seu código está estruturado?

Não estou falando sobre escrever o código de espaguete mais horrível e considerar apenas um aspecto dele, que provavelmente seria um fardo. Mas, no final, o que eu pretendo é: por que realizar a separação física do código, por que dividir o código em arquivos ou blocos separados (métodos), quando não é necessário se concentrar mentalmente em um aspecto?

A separação de preocupações deve permanecer um exercício mental, e não físico?
Em outras palavras, deve haver uma desconexão entre os aspectos mental (foco) e físico (código no papel) da programação?


5
Tenho certeza de que, em 1974, ele apenas viu a programação modular como um dado óbvio, e é por isso que não a discutiu explicitamente nesse artigo. O artigo de Parnas sobre como modularizar foi em 1972 e, nessa época, se modularizar já não era mais uma questão. De fato, o que você descreve não é sequer programação modular, é programação estruturada , que o próprio Dijkstra argumentou fortemente a favor de já em 1968 em seu clássico artigo "Go To Considered Harmful".
Jörg W Mittag

tudo bem, então talvez eu possa entender a "separação de preocupações" mais como um exercício de foco mental e a modularização como uma maneira de encapsular um aspecto do código no papel. No entanto, agora vejo a separação de preocupações e a modularização mais como conceitos separados.
Dennis

@ JörgWMittag, você pode definir a distinção entre programação estruturada e modular? Alguns links no google sugerem que eles são os mesmos.
Dennis

Estruturado = IF, WHILE, FORem vez de GOTO. Modular = módulos com uma API pública bem definida, estritamente separada de uma implementação e representação interna oculta. (Por exemplo, Modula, Mesa, Modula-2, Modula-3, depois dialetos em Pascal ( UNIT).)
Jörg W Mittag

Respostas:


2

Dijkstra está fazendo uma declaração explícita sobre como pensar. A modularização do programa (e processo) - e sua conveniência - é talvez o resultado desse pensamento, mas o ponto principal que ele está destacando é como avaliar um problema. O programa normalmente é a solução para um problema e, ao defender uma "separação de preocupações", ele oferece conselhos sábios. O melhor exemplo disso é talvez "otimização". A piada era: "Ao planejar otimizar um programa, sua primeira estratégia deve ser: não." Em outras palavras, você quer se concentrar primeiro em tornar o programa correto. Torná-lo rápido e sofisticado é uma preocupação que deve ser separada - mas também não deve ser completamente removida.


14

A separação de preocupações é uma maneira abstrata de pensar que consiste em considerar separadamente coisas que não precisam ser relacionadas.

Modularização (separando um grupo de funções não relacionadas em módulos), encapsulamento (ocultando detalhes internos dos módulos) e abstração (separando o geral do específico e a ideia de sua implementação) são todos meios para implementar essa maneira de pensar no domínio de design de software.


9

Eu sugeriria que, embora o artigo seja de interesse histórico, o que Dijkstra quis dizer com o termo "separação de preocupações" há mais de 40 anos não é particularmente relevante hoje. Atualmente é amplamente utilizado em referência à modulação.

Existem inúmeras evidências de que a modulização é extremamente benéfica e que esses benefícios superam em muito os "encargos" que ela impõe a nós. O que quer que Dijkstra quis dizer na época, não muda o fato de que pequenos pedaços de código, cada um focado em apenas uma coisa, levam a códigos mais fáceis de escrever, ler, entender, manter e testar.


5
Penso que deve-se notar que grande parte do pensamento moderno sobre Separação de Preocupações veio de artigos anteriores que acabaram gerando a Programação Orientada a Aspectos da IBM. Eu acho que os trabalhos iniciais (finais dos anos 90 e início dos anos 2000) são a maior influência lá. Já faz um tempo e os sites mudaram. Não tenho certeza se posso encontrá-los novamente.
Berin Loritsch

2
A parte difícil é tentar definir o que "uma coisa" significa. Sem isso, a idéia é inútil em termos de escrita prática de códigos, e errar tem efeitos imediatamente prejudiciais na dificuldade de escrever, ler, entender, manter e testar o código.
precisa saber é o seguinte

11
Isso realmente nos ajudaria a entender sua posição se você (a) explique o que acha que Dijkstra quis dizer com "separação de preocupações" e (b) explique POR QUE você acha que o que ele quis dizer não é mais relevante.
John R. Strohm

2

Eu posso lhe dar um exemplo pessoal de separação de preocupações que eu acho que é comparável aos conceitos de Dijkstra. Quando analiso um assunto em particular no software, construo três visualizações.

  1. Primeiro, considero os dados. Os dados representam os predicados lógicos do problema. As classes são construídas para abstrair entidades no mundo real, com seus atributos sendo os parâmetros da abstração. Associações entre classes representam mapeamentos funcionais entre as instâncias de classe. Não há código envolvido no pensamento neste momento e nenhuma noção de qualquer processamento. Apenas uma visão estática da lógica envolvida no assunto.
  2. Segundo, considero a dinâmica. Qualquer classe que tenha um ciclo de vida não trivial é modelada como uma máquina de estados finitos. Isso envolve considerações de execução e sincronização de sequenciamento. Mais uma vez, nenhum código apenas descobriu como as coisas interagem e sequenciam.
  3. Terceiro, considero o processamento. Aqui, o trabalho algorítmico real que deve ser realizado em transições de estado ou em outras operações síncronas.

No final, obtém-se uma visão tridimensional do assunto que pode ser formulada como código em quaisquer agrupamentos convenientes para o próprio código e sua manutenção. As três facetas não são apenas um exercício mental. Eu produzo descrições escritas de todas as facetas. Por quê? Porque, se o assunto for grande o suficiente, não posso conter nem uma faceta completa na memória de curto prazo. Se o assunto for pequeno, quase qualquer abordagem funcionará porque você pode manter tudo na cabeça.

A motivação para separar as preocupações é acomodar as limitações de memória de curto prazo dos seres humanos. Simplesmente não podemos carregar tudo em nossas cabeças ao mesmo tempo, embora os programadores de computador tendam a ser mais capazes do que a maioria das outras pessoas no número de conceitos que eles podem manipular em sua memória de curto prazo. Para ser eficaz, separar as preocupações deve sistematicamenteexcluir um ou mais aspectos de um problema para focar em outro aspecto específico. Evidentemente, excluir um aspecto não o faz desaparecer de consideração. Deve haver um meio de combinar todos os aspectos do problema para obter uma solução. A experiência mostra que, muitas vezes, o resultado final da separação e recombinação produz uma solução mais compreensível do que um único salto gigante, onde muitos aspectos podem ser misturados. Este é particularmente o caso quando o tamanho do problema é grande ou complicado.


1

Separação de preocupações é um conceito lógico que será propagado para o seu modelo de organização de código, não importa como você o implemente. É verdade que um arquivo de código é apenas um detalhe técnico, uma maneira de manter seu software gerenciado. Um único arquivo com um bom editor que permite recolher uma expansão de regiões também pode funcionar para você (por um tempo). Ou um banco de dados relacional que armazena classes e métodos de maneira pai-filho em tabelas separadas pode funcionar como um meio de armazenamento. Mas é difícil bater arquivos de texto em um mundo em que o código-fonte precisa ser

  • portátil
  • acessível por várias ferramentas externas diferentes
  • acessível por vários programadores
  • versionável e comparável
  • dimensionar bem com sistemas operacionais que são muito bons no manuseio de arquivos

O ponto principal é que nós, humanos, não somos muito bons em pensar ou lidar com coisas diferentes ao mesmo tempo. Portanto, precisamos de um modelo que permita pensar e trabalhar em uma coisa de cada vez, sem o risco de arruinar outra parte que não estamos considerando naquele momento. Então, construímos, colocando um tijolo de cada vez, certificando-nos de que os tijolos que deitamos antes não interfiram com os tijolos deitados depois. E se quisermos mudar um tijolo mais tarde, as coisas não devem entrar em colapso. Esse é um modelo que funciona para nossas mentes de uma pista.

Não é assim que crescem fungos ou algas ... Como é isso para um fato humilhante?


-1

Acredito que a resposta específica à citação de Dijkstra tenha sido abordada, no entanto, desde que você declare "Usando o OO moderno, eu poderia colocar o acesso a dados em seu próprio arquivo" e pergunte "A separação de preocupações deve continuar sendo um exercício mental, e não físico?" deixe-me chamar sua atenção para onde os diretores modernos de OO nos direcionam.

Deve-se seguir os princípios do SOLID no desenvolvimento usando OO. Aqui está um link interessante para eles, mas o TLDR sobre "separação de preocupações" está principalmente no S do SOLID: o princípio de responsabilidade única ou SRP.

Definitivamente, este é um exercício físico, não mental. Para seu exemplo específico, o MVC (ou seus irmãos MVVM e MVP) direciona um para separar fisicamente os shows de Model, View e Controller / Presenter / ViewModel em arquivos separados. Eu já vi algumas implementações do MVVM em que elas são implementadas em assemblies separados para restringir ainda mais a tendência de "misturar conceitos".

Mas. Vai além do simples "esta é uma visão e este é um modelo", se você seguir a visão do tio Bob sobre isso.

É preciso considerar também a fonte dos requisitos para qualquer elemento OO específico. Se você está misturando, digamos, o que o Cliente deseja com o que o Pessoal de Operações deseja, também está violando o SRP. Ou, colocando-o como o tio Bob: Uma classe deve ter um e apenas um motivo para mudar.

Eu recomendo que você pesquise mais usando os links fornecidos ou faça uma pesquisa na web por "princípios sólidos".


Não. Os princípios do SOLID estão tão desconectados da realidade de escrever código (= filosóficos) que só podem ser entendidos de maneira remotamente útil quando você já sabe escrever um bom código, quando é redundante na melhor das hipóteses. Usá-los como princípios orientadores sem já ter experiência e capacidade produz um código extremamente ruim.
precisa saber é
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.