Falta um modificador em Java?

Olá a todos!

Pesquisei no fórum e não achei nada relacionado, portanto resolvi postar.

A algum tempo venho observando que talvez a linguagem precise de um modificador extra, esse modificador faria o papel de manter as classes públicas acessíveis somente dentro do arquivo Jar que as contem.

Ex. Adicione qualquer framework ao seu projeto e logo vc verá que poderá importar e utilizar qualquer classe pública deste. Sendo que teoricamente vc deveria ter acesso somente as classes que você realmente irá precisar.

É possivel fazer isso usando OSGI por exemplo mas ter um modificador com essa funcionalidade não seria muito mais fácil?

Concordam? Discordam?

Aguardo opiniões!

Falta sim, até que isso está previsto para entrar no Java 8 (não vai dar tempo para entrar no java 7).

http://openjdk.java.net/projects/jigsaw/

O projeto Jigsaw não é muito diferente do OSGI: não vai criar nenhum modificador novo, apenas um arquivo separado onde você define o que será público fora do pacote.

Eu sei que em Scala, existe o modificador private por pacote. Seria mais ou menos assim:

private[com.example.mypackage] def myFunction() = ...

Indica que qualquer método de qualquer classe deste pacote tem visibilidade desta função. Agora, não lembro se os subpacotes conseguem vê-lo também. Se for possível, é exatamente o que você precisa.

P.S.: Pra mim Java 7 já virou “Duke Nuke Forever”, imagina o Java 8.

Eu acho que isso só vai complicar as coisas. Tem muita coisa que poderia melhorar que é muito mais importante do que um modificador desses…

Acho os modificadores do Java extremamente permissivos.
Por que o protected abre tanto para as classes do mesmo pacote?

De privado mesmo você praticamente só tem o private.

Sempre pensei nesse ponto relacionando-o com a arquitetura multi-camadas. Embora você separe sua aplicação nas camadas A - B - C. Não há uma solução natural java que impeça que A acesse C.

Também sempre me fiz a mesma pergunta do Vini.

atualmente para suprir isso acabo controlando isto via JDepend com testes unitários

Opa!

Claro que existem coisas muito mais importantes, mas é algo pequeno e pouco complexo mas que faria muita diferença, discordo quanto a complicar as coisas, pelo contrário, facilitaria e muito! pois evitaria que algum chato mecha aonde não deve, melhora o encapsulamento e ainda torna os componentes de uma forma geral menos propensos a erros.

Eu sou até contra o uso do final hauhauhauha.

O melhor é ser extensivo somente em alguns casos o bloqueio deve existir :slight_smile:

existe private package ???

pacote privado? o q seria?

Em C# existe o modificador internal:

Neste caso a classe MinhaClasse só é acessível dentro da mesma DLL :slight_smile:

o “internal” foi uma forma muito simples e prática de resolver esse problema que o Anders Hejslberg (sempre ele :slight_smile: ) achou no Java. Agora o Jigsaw é bem mais complicado :frowning:

Eu vejo que falta a linguagem Java o conceito de módulo.
Muitos pensam em pacotes como módulos. E até certo ponto, vejo isso como correto. Acontece que os pacotes são divisões mais lógicas do que físicas, mesmo eles sendo representados como pastas.
Para as DLLs(das antigas. No C# eu não sei se é assim) é mais fácil isso, pois elas são criadas para uma plataforma específica, numa linguagem específica, dentro de ambientes de desenvolvimento mais rígidos.

Eu digo que falta o conceito de módulo a linguagem Java especificamente, pois a comunidade de desenvolvimento tem esse conceito bem definido, e o projeto Jigsaw vem trazer esse conceito ao SDK do Java. Mas, a linguagem em si ainda não possui esse conceito. Falta uma abstração de mais alto nível para um módulo. Hoje em dia, temos que criar interfaces, proteger classes e fazer malabarismos para fornecermos um camada de comunicação externa, e ainda manter integro o encapsulamento, e não permitir que outros acessem coisas indevidas.

Sou desenvolvedor C# e recentemente comecei a usar Java.
Uma das coisas que percebi é justamente o que nosso amigo ali falou:

"Sempre pensei nesse ponto relacionando-o com a arquitetura multi-camadas. Embora você separe sua aplicação nas camadas A - B - C. Não há uma solução natural java que impeça que A acesse C. "

Em C# (geralmente) cada camada é separada em DLLs diferentes, sendo assim, é possível informar qual “camada” tem acesso à outras “camadas”.

[quote=ozix]Sempre pensei nesse ponto relacionando-o com a arquitetura multi-camadas. Embora você separe sua aplicação nas camadas A - B - C. Não há uma solução natural java que impeça que A acesse C.

Também sempre me fiz a mesma pergunta do Vini.[/quote]

Exato!

Quando a modularização, isso já pode ser resolviso com OSGI mesmo mas e como ficam os jars que usamos como dependencias?

Eu adiciono Hibernate + Spring + Framework qualquer, vou no netbeans digito a letra C e depois Ctrl+space, pronto… tenho aí umas centenas de classes que posso usar indevidamente.

Modificadores de acesso me parecem mais uma solução técnica para um problema social de falta de conhecimento¹.

Edit:

1 - Falta de conhecimento de como usar as classes de um sistema/framework do jeito certo/esperado pelo autor.

[quote=ViniGodoy]Acho os modificadores do Java extremamente permissivos.
Por que o protected abre tanto para as classes do mesmo pacote?

De privado mesmo você praticamente só tem o private.[/quote]

Porque o java é desenhado para hierarquia de pacotes e a herança pode ser cross-package. O pacote é um membro importante do java porque é usado para várias coisas na jvm. Segurança, entre elas. O Package é um conjunto de Class.

Não faltam modificadores no java, o que falta é o conceito de pacote filho. normalmente criamos o pacote X e depois o pacote X.Y onde Y serve para alguma coisa particular de X, por exemplo, X é interfaces e Y é implementações. Este vicio é levou a considerar que o java é imcompleto, quando na realidade é esta prática que está errada. Apenas classes da API que podem ser usadas fora do pacote devem ser publicas. O resto deve ser tudo package. É por isso que o package é o default, porque é assim que deveria ser feito.

Protected é para herança entre pacotes. Ele é mais permissivo que o package e menos que o public. Só que as pessoas não o sabem usar. O problema é esse e não a especificação do java. Por exemplo, métodos auxiliares declarados em classes abstratas devem ser protected e não public, como é costume ver por ai.

As anotações do projeto jigsaw não são para aumentar ou substituir os modificadores de visibilidade, são feitas para criar um novo conceito de bundle (que eles chama modulo) que é um conjunto de pacotes. (Bundle -> pacote -> class ). Na realidade está havendo uma evolução e não um remendo. O conceito é definir permissões de visibilidade entre modulos e pacotes e não entre classes como fazem os modificadores de visibilidade.
Com modulos é possivel fazer mais coisas interessantes em segurança e gerenciamento de dependencia como o OSGI já mostrou.

[quote=sergiotaborda]Porque o java é desenhado para hierarquia de pacotes e a herança pode ser cross-package. O pacote é um membro importante do java porque é usado para várias coisas na jvm. Segurança, entre elas. O Package é um conjunto de Class.

Não faltam modificadores no java, o que falta é o conceito de pacote filho. normalmente criamos o pacote X e depois o pacote X.Y onde Y serve para alguma coisa particular de X, por exemplo, X é interfaces e Y é implementações. Este vicio é levou a considerar que o java é imcompleto, quando na realidade é esta prática que está errada. Apenas classes da API que podem ser usadas fora do pacote devem ser publicas. O resto deve ser tudo package. É por isso que o package é o default, porque é assim que deveria ser feito. [/quote]

Claro, siga essa recomendação e você acabará com pacotes enormes, cheios de classes, o que vai contra qualquer prática sensata de modelagem. Não é à toa que a própria API do Java foi a primeira a desrespeitar a regra, e usar o conceito de subpacotes erroneamente.

E, como vc mesmo falou, falta o conceito de pacote filho. Essa falta é uma falha da especificação, não dos programadores. Subpacotes eram usados muito antes do java sequer existir.

Não concordo com você. O problema surgiu porque a especificação do java é ruim nesse aspecto. Programar seguindo a forma que foi feito é simplesmente inviável. Você acabaria com pacotes gigantescos e desorganizados. A recomendação de criar subpacotes está em artigos da Sun, embora haja a ressalva de que isso seja para organização do programador, e que para a linguagem são pacotes diferentes. A própria convenção de nomes de pacotes da a noção de hierarquia, que para linguagem não existe.

O único modificador que você tem que torna as coisas mais privadas é o private. Classes num mesmo pacote enxergam umas as outras com todas as suas propriedades públicas, exceto as private. É difícil modelar blocos de componentes em java por causa disso, é difícil garantir extensibilidade para fora do pacote sem ser permissivo demais para dentro do pacote.

Agora, não acho que a Sun tenha optado por uma abordagem de todo ruim. Talvez tenham optado por manter os modificadores simples, mesmo a custa de alguns problemas menores. E isso eles realmente são.

Opa!

Claro que podemos esconder tudo o que nao deve ser acessível ao mundo externo através do modificador default ou abrindo um pouco mais com protected. O problema é como o viny falou, se eu tenho um sistema que tem 1k classes como fica?

A própria estrutura de Sun (quer dizer… Oracle) usa esse modelo de sub-pacotes, o que eu acho que aconteceu é que ou numca se deu grande importancia a isso ou fazem vista grossa.

[quote=ViniGodoy][quote=sergiotaborda]Porque o java é desenhado para hierarquia de pacotes e a herança pode ser cross-package. O pacote é um membro importante do java porque é usado para várias coisas na jvm. Segurança, entre elas. O Package é um conjunto de Class.

Não faltam modificadores no java, o que falta é o conceito de pacote filho. normalmente criamos o pacote X e depois o pacote X.Y onde Y serve para alguma coisa particular de X, por exemplo, X é interfaces e Y é implementações. Este vicio é levou a considerar que o java é imcompleto, quando na realidade é esta prática que está errada. Apenas classes da API que podem ser usadas fora do pacote devem ser publicas. O resto deve ser tudo package. É por isso que o package é o default, porque é assim que deveria ser feito. [/quote]

Claro, siga essa recomendação e você acabará com pacotes enormes, cheios de classes, o que vai contra qualquer prática sensata de modelagem.
[/quote]

Não vejo onde está o problema disso. Nem vejo que isso seja um problema de modelagem. Organização de pacotes está longe de ser um problema de modelagem a menos que vc siga o padrão proposto pelo Java ( eu disse java, não sun).

Ao construir uma API grande como a do java é necessário tem em consideração que existem classes escondidas que vc não vê. A API publica é publica exatamente porque é que vc precisa usar, mas exste a API privada que tem apenas detalhes de implementação. Esta deve ser “secreta”.

Eu nunca vi muita utilidade na visibilidade padrão, até que comecei a criar API grandes como o MiddleHeaven. Existem coisas que vc precisa fazer mas que vc não quer publicar (até porque vc quer minimiar a superficie da API). Então o nivel default é realmente util na prática.

Em pacotes de negocio obviamente terá pouca utilidade já que os pacotes de dominio são os mais publicos que ha (afinal eles representam conceitos que existem na realidade e não detalhes de implementação).

Ter muitas classes num pacote não significa desordem. É esse conceito errado que leva as pessoas a criarem muitos subpacotes idiotas. Eu odeio especialmente o pacote impl. Um verdadeiro cancer. Não ha razão logica para segregar as implementações para outro pacote.

A regra base é muito simples ( tudo é private, apenas é aumentada a visibilidade quando necessário) mas - quase - ninguém a usa. e depois culpam o java …