A programação funcional ignora os benefícios obtidos com os "Sobre os critérios a serem usados ​​na decomposição de sistemas em módulos" (ocultação de dados)?


27

Há um artigo clássico chamado Sobre os critérios a serem usados ​​na decomposição de sistemas em módulos que acabei de ler pela primeira vez. Faz todo o sentido para mim e é provavelmente um daqueles artigos nos quais o OOP foi baseado. Sua conclusão:

Tentamos demonstrar por esses exemplos que quase sempre é incorreto iniciar a decomposição de um sistema em módulos com base em um fluxograma. ... Cada módulo é projetado para ocultar tal decisão dos outros

Na minha opinião sem instrução e inexperiente, a programação funcional segue exatamente o conselho oposto deste artigo. Meu entendimento é que a programação funcional torna o fluxo de dados idiomático. Os dados são transmitidos de função para função, cada função sendo intimamente ciente dos dados e "alterando-os" ao longo do caminho. E acho que vi um Rich Hickey falar onde ele fala sobre como a ocultação de dados é superestimada ou desnecessária ou algo assim, mas não me lembro com certeza.

  1. Primeiro, quero saber se minha avaliação está correta. O paradigma do PF e este artigo discordam filosoficamente?
  2. Supondo que discordem, como o FP "compensa" a falta de ocultação de dados? Talvez eles sacrificem a ocultação de dados, mas ganhem X, Y e Z. Gostaria de saber o motivo pelo qual X, Y e Z são considerados mais benéficos do que a ocultação de dados.
  3. Ou, supondo que discordem, talvez a FP pense que a ocultação de dados é ruim. Se sim, por que acha que a ocultação de dados é ruim?
  4. Supondo que eles concordem, eu gostaria de saber o que é a implementação dos FPs de ocultação de dados. É óbvio ver isso no OOP. Você pode ter um privatecampo que ninguém fora da classe possa acessar. Não há analogia óbvia disso para mim no FP.
  5. Sinto que há outras perguntas que devo fazer, mas não sei. Sinta-se à vontade para responder também.

Atualizar

Eu encontrei essa palestra de Neal Ford que tem um slide muito relevante. Vou incorporar a captura de tela aqui:

insira a descrição da imagem aqui


1
Não consigo responder à pergunta completa, mas quanto ao (4), existem sistemas de módulos em algumas linguagens FP que podem fornecer encapsulamento.
Andres F.

@AndresF. ah sim é verdade. Esqueci que o Haskell tem módulos e você pode ocultar tipos e funções de dados. Talvez quando eu digo FP eu esteja realmente dizendo Clojure. Você pode ter funções privadas e "campos" no Clojure, mas acho que é idiomático tornar seus dados visíveis a qualquer coisa e passá-los para qualquer lugar.
Daniel Kaplan

6
O que você costuma fazer é tornar seus tipos visíveis, mas oculta seus construtores. Estes tipos abstratos são feito particularmente bem pelo sistema módulo OCaml
Daniel Gratzer

6
Em uma linguagem do tipo ML, não ter acesso aos construtores significa que você não pode corresponder um padrão a um valor desse tipo para desconstruí-lo. A única coisa que você pode fazer com esses valores é passá-lo para qualquer função que foi disponibilizada. É o mesmo tipo de abstração de dados que é feito em, digamos, C, que também não possui noções de primeira classe do que é público ou privado.
Luc Danton

1
@ SK-logic: Do ponto de vista do "problema de expressão", revelar os dados é bom quando você deseja estender a nova função no futuro (e aceita manter os dados fixos) e ocultar os dados quando você deseja para estender com novos tipos de dados no futuro (com o custo de manter a interface funcional fixo)
hugomg

Respostas:


23

O artigo mencionado é sobre modularidade em geral e se aplicaria igualmente a programas estruturados, funcionais e orientados a objetos. Já ouvi falar desse artigo antes de alguém que era um grande sujeito de OOP, mas li como um artigo sobre programação em geral, não como algo específico de OOP. Há um artigo famoso sobre programação funcional, Why Functional Programming Matters , e a primeira frase da conclusão declara "Neste artigo, argumentamos que a modularidade é a chave para uma programação bem-sucedida". Portanto, a resposta para (1) é não.

Funções bem projetadas não assumem mais seus dados do que precisam, portanto a parte sobre "intimamente ciente dos dados" está errada. (Ou pelo menos tão errado quanto seria no OOP. Você não pode programar estritamente em um alto nível de abstração e ignorar todos os detalhes para sempre em qualquer paradigma. No final, alguma parte do programa realmente precisa saber sobre o detalhes específicos dos dados.)

Ocultar dados é um termo específico de POO e não é exatamente o mesmo que o oculto de informações discutido no artigo. As informações ocultas no artigo são sobre decisões de design difíceis de tomar ou que podem mudar. Nem todas as decisões de design sobre um formato de dados são difíceis ou podem mudar, e nem todas as decisões que são difíceis ou que podem mudar são sobre um formato de dados. Pessoalmente, não consigo entender por que os programadores de OO querem que tudo seja um objeto. Às vezes, basta uma estrutura de dados simples.

Edit: Encontrei uma citação relevante de uma entrevista com Rich Hickey .

Fogus: Seguindo essa ideia - algumas pessoas ficam surpresas com o fato de Clojure não se envolver no encapsulamento de ocultação de dados em seus tipos. Por que você decidiu renunciar à ocultação de dados?

Hickey: Sejamos claros que Clojure enfatiza fortemente a programação para abstrações. Em algum momento, porém, alguém precisará ter acesso aos dados. E se você tem uma noção de "privado", precisa das noções correspondentes de privilégio e confiança. E isso agrega muita complexidade e pouco valor, cria rigidez em um sistema e muitas vezes força as coisas a viver em lugares que não deveriam. Isso é um acréscimo à outra perda que ocorre quando informações simples são colocadas em classes. Na medida em que os dados são imutáveis, existem poucos danos ao fornecer acesso, exceto que alguém pode vir a depender de algo que pode mudar. Bem, tudo bem, as pessoas fazem isso o tempo todo na vida real e, quando as coisas mudam, elas se adaptam. E se eles são racionais, eles sabem quando tomam uma decisão com base em algo que pode mudar que eles possam, no futuro, precisar se adaptar. Portanto, é uma decisão de gerenciamento de riscos, que eu acho que os programadores devem ser livres para tomar. Se as pessoas não tiverem a sensibilidade de desejar programar para abstrações e desconfiar de se casar com os detalhes da implementação, nunca serão bons programadores.


2
Os programadores de OO não querem que tudo seja um objeto. Mas algumas coisas (muitas coisas) se beneficiam do encapsulamento. Estou com problemas para entender como ou onde sua resposta realmente aborda a questão. Parece apenas afirmar que o conceito não é específico para OOP e que OOP tem outros problemas e assim por diante - você pode fornecer um exemplo claro, mesmo que sejam apenas algumas linhas de pseudocódigo? Ou uma descrição do quadro branco de um design que leva isso em conta? Ou qualquer coisa que substanciaria as afirmações aqui?
Aaronaught

2
@Aaronaught: Abordei muitos (embora não todos) os pontos levantados na questão e referenciei um artigo sobre programação funcional que analisa a modularidade de maneira semelhante ao artigo da questão. Em grande parte, o fato de o conceito não ser específico para OOP é a resposta para sua pergunta (a menos que eu não tenha entendido completamente a pergunta). Eu realmente não falei sobre OOP tendo outros problemas aqui. Você tem um bom argumento em fornecer um exemplo; Vou ver se consigo encontrar uma boa.
Michael Shaw

2
"Às vezes, basta uma estrutura de dados simples". +1. Algo OOP faz sentido, às vezes é FP.
Laurent Bourgault-Roy

1
@Aaronaught Esta resposta indica que a modularidade (que é tanto o encapsulamento quanto a reutilização) é um dos objetivos do FP (conforme discutido em "Por que a programação funcional é importante"), fazendo com que a resposta ao ponto (1) da pergunta a " não".
Andres F.

2
@JimmyHoffa ocultar informações é um princípio sensato mesmo fora da OO. Em haskell, ainda quero que os usuários tenham permissão para trabalhar com uma quantidade mínima de conhecimento sobre qualquer estrutura de dados. Claro, ter acesso aos internos é menos perigoso, porque nada é mutável. Porém, quanto menos um usuário vê sobre um módulo / estrutura de dados / qualquer conceito abstrato, mais oportunidades de refatoração você obtém. Não me importo se um mapa for uma árvore binária equilibrada ou um mouse em uma pequena caixa no meu computador. Essa é a principal motivação por trás da ocultação de dados e é válida fora do OO.
Simon Bergot

12

... e provavelmente é um daqueles artigos nos quais o OOP foi baseado.

Na verdade, não, mas isso contribuiu para a discussão, especialmente para os profissionais que, na época, eram treinados para decompor sistemas usando os primeiros critérios que ele descreve no artigo.

Primeiro, quero saber se minha avaliação está correta. O paradigma do PF e este artigo discordam filosoficamente?

Não. Além disso, a meu ver, sua descrição de como é um programa FP não é diferente de nenhum outro que utilize procedimentos ou funções:

Os dados são transmitidos de função para função, cada função sendo intimamente ciente dos dados e "alterando-os" ao longo do caminho.

... exceto na parte "intimidade", já que você pode (e geralmente possui) funções operando em dados abstratos, precisamente para evitar a intimidade. Assim, você tem algum controle sobre essa "intimidade" e pode regulá-la como quiser, configurando interfaces (ou seja, funções) para o que deseja ocultar.

Portanto, não vejo razão para não sermos capazes de seguir os critérios de ocultação de informações de Parnas usando programação funcional e terminar com a implementação de um índice KWIC com benefícios semelhantes apontados como sua segunda implementação.

Supondo que eles concordem, eu gostaria de saber o que é a implementação dos FPs de ocultação de dados. É óbvio ver isso no OOP. Você pode ter um campo particular que ninguém fora da classe possa acessar. Não há analogia óbvia disso para mim no FP.

No que diz respeito aos dados, é possível elaborar abstrações de dados e abstrações de tipo de dados usando o FP. Qualquer um desses oculta estruturas e manipulações concretas dessas estruturas de concreto usando funções como abstrações.

EDITAR

Há um número crescente de afirmações aqui afirmando que "ocultar dados" no contexto do FP não é tão útil (ou OOP-ish (?)). Então, deixe-me carimbar aqui um exemplo muito simples e claro do SICP:

Suponha que seu sistema precise trabalhar com números racionais. Uma maneira de representá-los é como um par ou uma lista de dois números inteiros: o numerador e o denominador. Portanto:

(define my-rat (cons 1 2)) ; here is my 1/2 

Se você ignorar a abstração de dados, provavelmente obterá o numerador e o denominador usando care cdr:

(... (car my-rat)) ; do something with the numerator

Seguindo essa abordagem, todas as partes do sistema que manipulam números racionais saberão que um número racional é um cons- elas consnumerarão para criar racionais e extraí-las usando operadores de lista.

Um problema que você pode enfrentar é quando precisa ter uma forma reduzida dos números racionais - serão necessárias alterações em todo o sistema. Além disso, se você decidir reduzir no momento da criação, poderá descobrir mais tarde que reduzir ao acessar um dos termos racionais é melhor, gerando outra alteração em escala total.

Outro problema é se, hipoteticamente, uma representação alternativa é preferida e você decide abandonar a consrepresentação - mudança em escala completa novamente.

Qualquer esforço sensato para lidar com essas situações provavelmente começará a esconder a representação dos racionais por trás das interfaces. No final, você pode acabar com algo assim:

  • (make-rat <n> <d>)retorna o número racional cujo numerador é o número inteiro <n>e cujo denominador é o número inteiro <d>.

  • (numer <x>)retorna o numerador do número racional <x>.

  • (denom <x>)retorna o denominador do número racional <x>.

e o sistema não saberá mais (e não deve mais) saber do que são feitos os racionais. Isto porque cons, care cdrnão são intrínsecos à racionais, mas make-rat, numere denom são . Obviamente, isso poderia ser facilmente um sistema de FP. Portanto, "ocultação de dados" (neste caso, mais conhecido como abstração de dados ou o esforço de encapsular representações e estruturas concretas) surge como um conceito relevante e uma técnica amplamente utilizada e explorada, seja no contexto de OO, programação funcional ou tanto faz.

E o ponto é ... embora se possa tentar fazer distinções entre que "tipo de ocultação" ou encapsulamento eles estão fazendo (estejam escondendo uma decisão de design, estruturas de dados ou algoritmos - no caso de abstrações processuais), todos eles têm o mesmo tema: são motivados por um ou mais pontos que Parnas explicitou. Isso é:

  • Mudança: se as alterações necessárias podem ser feitas localmente ou espalhadas pelo sistema.
  • Desenvolvimento Independente: em que grau duas partes do sistema podem ser desenvolvidas em paralelo.
  • Compreensibilidade: quanto do sistema deve ser conhecido para entender uma de suas partes.

O exemplo acima foi retirado do livro do SICP, portanto, para a discussão e apresentação completa desses conceitos no livro, eu recomendo verificar o capítulo 2 . Eu também recomendo familiarizar-se com tipos de dados abstratos no contexto do FP, o que traz outros problemas para a tabela.


Concordo que a ocultação de dados é relevante no FP. E, como você diz, existem maneiras de conseguir isso.
Andres F.

2
Você acabou de fazer meu argumento lindamente: você tem essas funções que não estão ocultando dados, são expressões que descrevem como obter dados, assim, tendo a abstração em uma expressão e não em um campo de dados, você não precisa se preocupar em ocultar os dados criando um objeto complexo com membros privados ou tornando inacessíveis os seus valores contras, as atividades de geração e recuperação e interação com dados racionais são expressas; portanto, os dados racionais reais não precisam ser ocultados porque a alteração dos dados não será possível. mude suas expressões.
Jimmy Hoffa

8

Sua crença de que a programação funcional carece de ocultação de dados está errada. É preciso apenas uma abordagem diferente para ocultar dados. Uma das maneiras mais comuns de ocultar dados na programação funcional é através do uso de funções polimórficas que assumem uma função como argumento. Por exemplo, esta função

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

só pode ver a estrutura mais externa dos dados (ou seja, que é uma lista), não pode ver nada sobre os dados que a lista contém e só pode operar com os dados através da função única que é passada a ele.

A função que é passada como argumento é análoga a um método público no tipo de dados que a lista contém. Ele fornece uma maneira limitada de operar com os dados, mas não expõe o funcionamento interno do tipo de dados.


5

Vou atacar aqui e dizer que o conceito simplesmente não é relevante no FP da maneira como é no OO.

tl; dr; O objetivo da ocultação de dados é garantir que as responsabilidades sejam mantidas onde deveriam estar, e você não tem atores externos mexendo com dados que eles não conhecem. No FP, os dados são gerados por expressões e, dessa maneira, você não pode mexer com os dados, porque não são propriedades mutáveis, mas sim computações composíveis, que alteram completamente as regras do jogo.


Nas minhas experiências com FP; que são reconhecidamente insignificantes, tenho a tendência de encontrar um forte contraste com o OO no que denota boa / comum modelagem de dados.

Esse contraste é que, em OO em geral, você modela as coisas para representar seus dados. Analogia obrigatória do carro:

OO

  • Você tem um Objeto de carro, que oculta corretamente detalhes sobre o carro, como a implementação de CA (é acionada por correia ou acionada por pressão de ar? Os consumidores não precisam saber, então esconda-os).
  • Esse objeto de carro possui muitas propriedades e métodos que delineiam todos os fatos sobre o carro, bem como maneiras de trabalhar com ele.
  • Esse objeto de carro possui propriedades que são componentes de um carro que ocultam ainda mais o carro em geral, suas implementações particulares e seus dados, permitindo que os componentes do carro sejam intercambiáveis.

O ponto a ser observado aqui é que quando você está modelando itens em um formato OO, trata-se de representar itens como Dados. Você tem objetos com propriedades, muitas dessas propriedades são objetos com mais propriedades. Você tem alguns métodos aqui e ali anexados a esses objetos, mas tudo o que eles realmente fazem é geralmente agitar as propriedades dos objetos desta maneira e daquela; novamente, é uma modelagem muito centrada em dados; ou seja, você modela seus dados para interagir com o foco na estruturação para disponibilizar todos os pontos de seus dados, para que os consumidores possam alterar os dados dessa maneira e daquilo.

FP

  • Você tem muitos cálculos que permitem descrever comportamentos
  • Essas expressões de comportamento estão relacionadas de uma maneira que pode ser traduzida para a maneira como os comportamentos de um carro estão relacionados entre si, como um carro que acelera / desacelera, existem dois comportamentos que se opõem de maneira semelhante.

A grande diferença entre OO e FP que constantemente me impressiona é como eu disse acima da maneira como você modela os dados. No OO, como mencionado acima, você modela dados como dados, no FP, você modela dados como cálculos, expressões, algoritmos, trata-se mais da modelagem das atividades de seus dados do que dos fatos. Pense na modelagem de dados básica em matemática, é sempre sobre obter uma equação que pode gerar seus dados, que modela seus dados como a atividade que os causa, ao contrário da OO, a modelagem está criando uma maneira de representar os dados que você possui. Essa é grande parte da distinção entre FP e OO.

Lembre-se, por muito tempo, o LISP, uma das linguagens fundamentais do FP, viveu com uma quantidade muito pequena de tipos de dados primitivos. Isso funciona porque a abordagem não é modelar representações complexas de seus dados, mas sim computações que geram e expressam os comportamentos do seu sistema.

Quando começo a escrever algum código no FP, começo escrevendo um código que faz alguma coisa, enquanto que quando começo a escrever um código no OO, começo escrevendo modelos que descrevem alguma coisa. O fazer das coisas é oculto no FP por ser expressões, o fazer das coisas é exposto no OO ao ser descrito com dados, ocultar esses dados limita a referida exposição.


Voltando à pergunta em questão, o que a FP diz sobre a ocultação de dados, ela aprecia ou discorda dela ou não?

Eu digo que isso não importa, no OO seus dados são as entranhas e as partes importantes do seu programa que devem ser escondidas de serem intrometidas. No FP, as entranhas e o conhecimento do seu sistema estão todos ocultos nos algoritmos e cálculos que expressam o sistema. Essas são, por definição, mais ou menos imutáveis, a única maneira de modificar as expressões de computação são coisas como macros, mas mesmo assim, as definições de mutações são expressões em si que não podem ser mais intrometidas.


isso é brilhante, eu realmente gostei de ler. Obrigado pela sua contribuição
Chris McCall

5

Há um pouco de paradoxo aqui. Embora a programação funcional se concentre em, bem, funções e frequentemente tenha funções que funcionam diretamente em tipos de dados primitivos, ela tende a ter mais dados ocultos do que a programação orientada a objetos.

Como é isso? Pense em uma interface OO agradável que oculte dados subjacentes - talvez coleções (estou tentando escolher algo quase onipresente). Talvez você não precise conhecer o tipo subjacente dos objetos na coleção ou o tipo de objeto que implementa a coleção, desde que saiba que a coleção é implementada, por exemplo, IEnumerable. Então você tem ocultação de dados.

Na programação funcional, você pode escrever uma função que funcione efetivamente com uma interface IEnumerable, mas opere em um tipo de dados primitivo (ou em qualquer tipo de dado). Mas e se o tipo nunca implementasse os métodos IEnumerable? Aqui está a chave: você sempre pode ter os "métodos" que formam as partes necessárias da "interface" como parâmetros passados ​​para sua função. Ou você pode juntar funções com dados e fazer coisas de maneira OO.

Observe que, de qualquer forma, você não possui menos dados ocultos do que no OO. Minha função geral que funciona em qualquer tipo claramente não está acessando os dados nesse tipo - isso acontece nas funções passadas como parâmetros para a função geral, mas a função geral nunca espia dentro dessas funções para ver os dados.

Portanto, no que diz respeito ao seu ponto 1, não acho que o FP e o artigo realmente discordem. Eu não acho que sua caracterização de FP não oculte dados esteja correta. Alguém poderia implementar o design que o autor preferia no FP, certamente.

Quanto ao ponto 4 (2 e 3 não faz sentido responder, dado o que eu disse para o ponto 1), isso varia. Também varia nos idiomas OO e, em muitos campos particulares, é privado por convenção, e não imposto pelo idioma.


Em outras palavras: na programação funcional, muito mais é "oculto" por padrão, simplesmente porque nem existe! Somente coisas que você traz explicitamente para o escopo são "ocultas".
usar o seguinte código

3

Primeiro, obrigado pelo link para este excelente artigo, eu não sabia disso até agora, e isso me deu uma grande contribuição sobre algumas coisas que eu estava discutindo com outros designers de software da comunidade nos últimos anos. Aqui está a minha opinião sobre isso:

Primeiro, quero saber se minha avaliação está correta. O paradigma do PF e este artigo discordam filosoficamente?

O design do FP se concentra muito no fluxo de dados (o que é IMHO não tão ruim quanto o artigo pode sugerir). Se isso é um "desacordo" completo, é discutível.

Supondo que discordem, como o FP "compensa" a falta de ocultação de dados? Talvez eles sacrificem a ocultação de dados, mas ganhem X, Y e Z. Gostaria de saber o motivo pelo qual X, Y e Z são considerados mais benéficos do que a ocultação de dados.

IMHO não compensa. Ver abaixo.

Ou, supondo que discordem, talvez a FP pense que a ocultação de dados é ruim. Se sim, por que acha que a ocultação de dados é ruim?

Eu não acho que a maioria dos usuários ou designers de FP se sintam ou pensem dessa maneira, veja abaixo.

Supondo que eles concordem, eu gostaria de saber o que é a implementação dos FPs de ocultação de dados. É óbvio ver isso no OOP. Você pode ter um campo particular que ninguém fora da classe possa acessar. Não há analogia óbvia disso para mim no FP.

Aqui está o ponto - você provavelmente já viu tantos sistemas OOP implementados de uma maneira não funcional que acredita que o OOP não é funcional. E isso é uma falácia, IMHO OOP e FP são conceitos ortogonais e você pode criar perfeitamente sistemas OO funcionais, o que fornece uma resposta óbvia à sua pergunta. A implementação clássica de "objeto" no FP é feita utilizando fechamentos , e se você deseja que objetos sejam usados ​​em um sistema funcional, o ponto principal é projetá-los imutáveis.

Portanto, para criar sistemas maiores, IMHO, você pode criar módulos, classes e objetos usando os conceitos de OO, exatamente da maneira descrita em "Modularização 2" no artigo, sem sair do "caminho FP". Você usará o conceito de módulo da sua linguagem FP favorita, tornará imutáveis ​​todos os seus objetos e usará o "melhor dos dois mundos".


3

TL; DR : Não

O paradigma do FP e este artigo discordam filosoficamente ?.

Não, não faz. A Programação Funcional é declarativa, que é "um estilo de construção da estrutura e dos elementos dos programas de computador, que expressa a lógica de uma computação sem descrever seu fluxo de controle". É menos sobre seguir o fluxograma e mais sobre como criar as regras que permitem que o fluxo surja por si só.

A programação procedural está muito mais próxima de uma codificação de um fluxograma do que a programação funcional. Daqui resulta que as transformações que ocorrem e codificam essas transformações em procedimentos executados em ordem, exatamente como o fluxo em um fluxograma descreve.

Enquanto as linguagens procedurais modelam a execução do programa como uma sequência de comandos imperativos que podem implicitamente alterar o estado compartilhado, as linguagens de programação funcionais modelam a execução como a avaliação de expressões complexas que dependem apenas uma da outra em termos de argumentos e valores de retorno. Por esse motivo, os programas funcionais podem ter uma ordem mais livre de execução de código e os idiomas podem oferecer pouco controle sobre a ordem em que várias partes do programa são executadas. (Por exemplo, os argumentos para uma chamada de procedimento no esquema são executados em uma ordem arbitrária.)

Ocultar dados

  • A Programação Funcional possui seus próprios métodos de ocultação de dados, por exemplo, pense em fechamentos . São dados ocultados por encapsulamento em um fechamento. É difícil para os campos haver mais dados privados que foram fechados, pois apenas o fechamento tem uma referência aos dados e você não pode se referir a eles externos ao fechamento.
  • Uma das razões para ocultar dados é estabilizar a interface de programação ocultando dados mutantes. A programação funcional não possui dados mutantes, portanto, não precisa de tanta ocultação de dados.

3
"A programação funcional não possui dados mutantes; portanto, não precisa de tanta ocultação de dados". - esta é uma afirmação muito enganadora. Você mesmo disse (e eu concordo) que uma das razões para o comportamento de encapsular é ter controle sobre a mutação de dados. Mas concluir que a falta de mutação quase torna o encapsulamento inútil é um enorme esforço. ADTs e abstração de dados em geral são difundidos na literatura e nos sistemas FP.
Thiago Silva

Eu nunca disse que "quase torna o encapsulamento inútil". Esses são seus pensamentos e somente seus. Eu disse que você não precisa ocultar o máximo de dados devido à falta de variáveis ​​mutantes. Isso não torna inútil o encapsulamento ou a ocultação de dados, apenas reduz seu uso, porque esses casos não existem. Todos os outros casos em que a ocultação e o encapsulamento de dados são úteis ainda são válidos.
dietbuddha
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.