144.24.20.233: Added info in which package is the code snippet defined. - 2015-07-14 09:20:29

Added info in which package is the code snippet defined.

←Older revision Revision as of 09:20, 14 July 2015
Line 12: Line 12:
<source lang="java" snippet="design.less.friend.Item"/>
<source lang="java" snippet="design.less.friend.Item"/>
 +
(package org.apidesign.friendpackage.api)
This is regular [[Java]] code relying on the standard '''public''' and ''package private'' modifiers. This is exactly the code that you would write, if the friend code would reside in the same package as the API. As we want to use distinct packages, let us take another step and [[wikipedia::Teleport|teleport]] the API to another ''friend'' package with implementation classes. This can be done by defining an ''accessor'' class in such package:
This is regular [[Java]] code relying on the standard '''public''' and ''package private'' modifiers. This is exactly the code that you would write, if the friend code would reside in the same package as the API. As we want to use distinct packages, let us take another step and [[wikipedia::Teleport|teleport]] the API to another ''friend'' package with implementation classes. This can be done by defining an ''accessor'' class in such package:
<source lang="java" snippet="design.less.friend.Accessor"/>
<source lang="java" snippet="design.less.friend.Accessor"/>
 +
(package org.apidesign.friendpackage.impl)
This class defines an internal, friend API specifying what is the functionality that our implementation classes want to get from our API interfaces (in addition to regular access to all '''public''' elements). In this particular case it is the access to constructor via the ''newItem'' method and listener manipulation via ''addChangeListener'' method. Please note that these methods are abstract, without implementation and that this internal API is waiting for someone to register the implementation by calling the ''setDefault'' static method.
This class defines an internal, friend API specifying what is the functionality that our implementation classes want to get from our API interfaces (in addition to regular access to all '''public''' elements). In this particular case it is the access to constructor via the ''newItem'' method and listener manipulation via ''addChangeListener'' method. Please note that these methods are abstract, without implementation and that this internal API is waiting for someone to register the implementation by calling the ''setDefault'' static method.
Line 22: Line 24:
<source lang="java" snippet="design.less.friend.AccessorImpl"/>
<source lang="java" snippet="design.less.friend.AccessorImpl"/>
 +
(package org.apidesign.friendpackage.api)
Place this non-public ''AccessorImpl'' next to the ''Item'' class, so they are friends in the classical [[Java]] sense. Now all our intrinsic classes are ready. We have the public API class ''Item'' with hooks for friends, we have the API for friends in the ''Accessor'' class and we also have a provider of this friend API. Now we need to bind this all together. As soon as the ''Item'' class is loaded, we need to register the implementation. In [[Java]] this can be done with the use of '''static''' initializer block in the API class:
Place this non-public ''AccessorImpl'' next to the ''Item'' class, so they are friends in the classical [[Java]] sense. Now all our intrinsic classes are ready. We have the public API class ''Item'' with hooks for friends, we have the API for friends in the ''Accessor'' class and we also have a provider of this friend API. Now we need to bind this all together. As soon as the ''Item'' class is loaded, we need to register the implementation. In [[Java]] this can be done with the use of '''static''' initializer block in the API class:
<source lang="java" snippet="design.less.friend.Item.static"/>
<source lang="java" snippet="design.less.friend.Item.static"/>
 +
(package org.apidesign.friendpackage.api)
And this is all (especially if we want as [[Cluelessness|clueless]] understanding as possible). We have connected two [[Java]] packages together and provided an API that allows them to perform a ''privileged'' communication. As such any code in the same package as the ''Accessor'' class can call:
And this is all (especially if we want as [[Cluelessness|clueless]] understanding as possible). We have connected two [[Java]] packages together and provided an API that allows them to perform a ''privileged'' communication. As such any code in the same package as the ''Accessor'' class can call:
<source lang="java" snippet="design.less.friend.use"/>
<source lang="java" snippet="design.less.friend.use"/>
 +
(package org.apidesign.friendpackage.impl)
Moreover, because all the methods in the ''Accessor'' class are '''protected''' and there is just one reasonable subclass, only code in this one package can make the calls, no code in other packages has any chance to access these methods. As such the solution is safe and creates a secure [[wikipedia::Teleport|teleport]] between the API package and the implementation one, allowing us to separate interfaces and implementation as advised by
Moreover, because all the methods in the ''Accessor'' class are '''protected''' and there is just one reasonable subclass, only code in this one package can make the calls, no code in other packages has any chance to access these methods. As such the solution is safe and creates a secure [[wikipedia::Teleport|teleport]] between the API package and the implementation one, allowing us to separate interfaces and implementation as advised by

JaroslavTulach: APIDesignPatterns:FriendPackages moved to FriendPackages - 2008-11-15 12:38:46

APIDesignPatterns:FriendPackages moved to FriendPackages

←Older revision Revision as of 12:38, 15 November 2008

JaroslavTulach at 12:38, 15 November 2008 - 2008-11-15 12:38:34

←Older revision Revision as of 12:38, 15 November 2008
Line 33: Line 33:
Moreover, because all the methods in the ''Accessor'' class are '''protected''' and there is just one reasonable subclass, only code in this one package can make the calls, no code in other packages has any chance to access these methods. As such the solution is safe and creates a secure [[wikipedia::Teleport|teleport]] between the API package and the implementation one, allowing us to separate interfaces and implementation as advised by
Moreover, because all the methods in the ''Accessor'' class are '''protected''' and there is just one reasonable subclass, only code in this one package can make the calls, no code in other packages has any chance to access these methods. As such the solution is safe and creates a secure [[wikipedia::Teleport|teleport]] between the API package and the implementation one, allowing us to separate interfaces and implementation as advised by
[[Code Against Interfaces, Not Implementations]] wisdom.
[[Code Against Interfaces, Not Implementations]] wisdom.
 +
 +
 +
[[Category:APIDesignPatterns]]
 +
[[Category:APIDesignPatterns:Encapsulation]]

JaroslavTulach at 12:39, 24 October 2008 - 2008-10-24 12:39:42

←Older revision Revision as of 12:39, 24 October 2008
Line 1: Line 1:
Common [[wikipedia::Object-oriented_programming_language|object oriented languages]] offer some kind of [[encapsulation]], which often takes form of having '''public''', '''protected''' and '''private''' access modifiers. Indeed, designers soon found that this is not enough and as such [[C++]] has '''friend''' keyword and [[Java]] adds additional ''package private'' access type.
Common [[wikipedia::Object-oriented_programming_language|object oriented languages]] offer some kind of [[encapsulation]], which often takes form of having '''public''', '''protected''' and '''private''' access modifiers. Indeed, designers soon found that this is not enough and as such [[C++]] has '''friend''' keyword and [[Java]] adds additional ''package private'' access type.
-
The problem with the [[Java]] approach is that it generally dictates the files layout of your friends. Their sources need to be placed in the same directory. Many people do not like that, as this mixes the classes representing the API with the classes that provider their implementation. This is not perfect. Common wisdom and also [[Code Against Interfaces, Not Implementations|Chapter 8]] advice, that it is preferable to ''code against interfaces and not the implementation''. The [[Code Against Interfaces, Not Implementations|Chapter 8]] explains that this old good advice can have various meanings and take multiple forms. One of such forms is the practise of putting the implementation and interfaces sources in two distinct disk locations. This is exactly against the requirements of the [[Java]]'s ''package private'' access modifier, making it useless for establishing friendship between distinct API and implementation packages.
+
The problem with the [[Java]] approach is that it generally dictates the files layout of your friends. Their sources need to be placed in the same directory. Many people do not like that, as this mixes the classes representing the API with the classes that provide their implementation. This is not perfect. Common wisdom and also [[Code Against Interfaces, Not Implementations|Chapter 8]] advice, that it is preferable to ''code against interfaces and not the implementation''. The [[Code Against Interfaces, Not Implementations|Chapter 8]] explains that this old good advice can have various meanings and take multiple forms. One of such forms is the practise of putting the implementation and interfaces sources in two distinct disk locations. This is exactly against the requirements of the [[Java]]'s ''package private'' access modifier, making it useless for establishing friendship between distinct API and implementation packages.
This often leads people to open the APIs up and use '''public''' or '''protected''' modifiers, sometimes annotating the method with a javadoc note ''do not call me, I am part of the implementation''. This is unfortunate as it pollutes the APIs with useless implementation details, distracts the API users and potentially creates security holes in the API.
This often leads people to open the APIs up and use '''public''' or '''protected''' modifiers, sometimes annotating the method with a javadoc note ''do not call me, I am part of the implementation''. This is unfortunate as it pollutes the APIs with useless implementation details, distracts the API users and potentially creates security holes in the API.

JaroslavTulach: /* Friend Packages */ - 2008-10-24 12:02:37

Friend Packages

←Older revision Revision as of 12:02, 24 October 2008
Line 27: Line 27:
<source lang="java" snippet="design.less.friend.Item.static"/>
<source lang="java" snippet="design.less.friend.Item.static"/>
-
And this is all (especially if we want as [[Cluelessness|clueless]] understanding as possible). We have just bind two [[Java]] packages together and provided an API that allows them to perform a ''privileged'' communication. As such any code in the same package as the ''Accessor'' class can call:
+
And this is all (especially if we want as [[Cluelessness|clueless]] understanding as possible). We have connected two [[Java]] packages together and provided an API that allows them to perform a ''privileged'' communication. As such any code in the same package as the ''Accessor'' class can call:
<source lang="java" snippet="design.less.friend.use"/>
<source lang="java" snippet="design.less.friend.use"/>
-
Because all the methods in the ''Accessor'' class are '''protected''', only code in this one package can make the calls, no code in other packages has any chance to call these methods. As such the solution is safe and creates a secure [[wikipedia::Teleport|teleport]] between the API package and the implementation one.
+
Moreover, because all the methods in the ''Accessor'' class are '''protected''' and there is just one reasonable subclass, only code in this one package can make the calls, no code in other packages has any chance to access these methods. As such the solution is safe and creates a secure [[wikipedia::Teleport|teleport]] between the API package and the implementation one, allowing us to separate interfaces and implementation as advised by
 +
[[Code Against Interfaces, Not Implementations]] wisdom.

JaroslavTulach: /* Friend Packages */ - 2008-10-24 11:57:55

Friend Packages

←Older revision Revision as of 11:57, 24 October 2008
Line 17: Line 17:
<source lang="java" snippet="design.less.friend.Accessor"/>
<source lang="java" snippet="design.less.friend.Accessor"/>
-
This class defines an internal, friend API specifying what is the functionality that our implementation classes want to get from our API interfaces (in addition to regular access to all '''public''' elements). In this particular case it is the access to constructor via the ''newItem'' and listener via ''addChangeListener'' methods. Please note that these methods are abstract, without implementation and that this internal API is waiting for someone to register the implementation by calling the ''setDefault'' static method.
+
This class defines an internal, friend API specifying what is the functionality that our implementation classes want to get from our API interfaces (in addition to regular access to all '''public''' elements). In this particular case it is the access to constructor via the ''newItem'' method and listener manipulation via ''addChangeListener'' method. Please note that these methods are abstract, without implementation and that this internal API is waiting for someone to register the implementation by calling the ''setDefault'' static method.
-
Who can provide implementation of this class? Well, only someone who can call the ''package private'' methods from the ''Item'' class. Does a class like that exist? Indeed, it does, any class in the same package as ''Item'' can do that. So just write:
+
Who can provide meaningful implementation of this class? Well, only someone who can call the ''package private'' methods from the ''Item'' class. Does a class like that exist? Indeed, it does, any class in the same package as ''Item'' can do that. So just write:
<source lang="java" snippet="design.less.friend.AccessorImpl"/>
<source lang="java" snippet="design.less.friend.AccessorImpl"/>
-
Now we have the public API class ''Item'' with hooks for friends, we have the API for friends in the ''Accessor'' class and we also have a provider of this friend API. Now we need to bind this all together. As soon as the ''Item'' class is loaded, we need to register the implementation. In [[Java]] this can be done with the use of '''static''' initializer block in the API class:
+
Place this non-public ''AccessorImpl'' next to the ''Item'' class, so they are friends in the classical [[Java]] sense. Now all our intrinsic classes are ready. We have the public API class ''Item'' with hooks for friends, we have the API for friends in the ''Accessor'' class and we also have a provider of this friend API. Now we need to bind this all together. As soon as the ''Item'' class is loaded, we need to register the implementation. In [[Java]] this can be done with the use of '''static''' initializer block in the API class:
<source lang="java" snippet="design.less.friend.Item.static"/>
<source lang="java" snippet="design.less.friend.Item.static"/>

JaroslavTulach: /* Friend Packages */ - 2008-10-24 11:52:27

Friend Packages

←Older revision Revision as of 11:52, 24 October 2008
Line 13: Line 13:
<source lang="java" snippet="design.less.friend.Item"/>
<source lang="java" snippet="design.less.friend.Item"/>
-
This is a regular [[Java]] code relying on the standard '''public'' and ''package private'' modifiers. No surprises so far, the next quest is to [[wikipedia::Teleport|teleport]] the API to the friend package with implementation classes. This can be done by defining an ''accessor'' class in such package:
+
This is regular [[Java]] code relying on the standard '''public''' and ''package private'' modifiers. This is exactly the code that you would write, if the friend code would reside in the same package as the API. As we want to use distinct packages, let us take another step and [[wikipedia::Teleport|teleport]] the API to another ''friend'' package with implementation classes. This can be done by defining an ''accessor'' class in such package:
<source lang="java" snippet="design.less.friend.Accessor"/>
<source lang="java" snippet="design.less.friend.Accessor"/>

JaroslavTulach at 11:48, 24 October 2008 - 2008-10-24 11:48:59

←Older revision Revision as of 11:48, 24 October 2008
Line 5: Line 5:
This often leads people to open the APIs up and use '''public''' or '''protected''' modifiers, sometimes annotating the method with a javadoc note ''do not call me, I am part of the implementation''. This is unfortunate as it pollutes the APIs with useless implementation details, distracts the API users and potentially creates security holes in the API.
This often leads people to open the APIs up and use '''public''' or '''protected''' modifiers, sometimes annotating the method with a javadoc note ''do not call me, I am part of the implementation''. This is unfortunate as it pollutes the APIs with useless implementation details, distracts the API users and potentially creates security holes in the API.
-
One of the solutions is to add yet another modifiers to [[Java]] and introduce concept of ''friend packages''. This may happen occasionally. Meanwhile he is little [[APIDesignPatterns|API design pattern]] that makes that possible now.
+
One of the solutions is to add yet another modifiers to [[Java]] and introduce concept of ''friend packages''. This may happen occasionally. Meanwhile let's learn how to use simple [[APIDesignPatterns|API design pattern]] that makes connecting two packages possible even now.
== Friend Packages ==
== Friend Packages ==

JaroslavTulach at 11:46, 24 October 2008 - 2008-10-24 11:46:00

←Older revision Revision as of 11:46, 24 October 2008
Line 1: Line 1:
-
Common [[wikipedia::Object-oriented_programming_language|object oriented languages]] offer some kind of [[encapsulation]], which often takes form of having '''public''', '''protected''' and '''private''' access modifiers. Indeed, designers soon found that this is not enough and as such [[C++]] has ''friend'' constructs and [[Java]] adds additional ''package private'' access type.
+
Common [[wikipedia::Object-oriented_programming_language|object oriented languages]] offer some kind of [[encapsulation]], which often takes form of having '''public''', '''protected''' and '''private''' access modifiers. Indeed, designers soon found that this is not enough and as such [[C++]] has '''friend''' keyword and [[Java]] adds additional ''package private'' access type.
-
The problem with the [[Java]] approach is that it generally dictates the files layout of your friends. They need to be placed in the same directory. Many people do not like that, as this mixes the classes representing the API with the classes that implement them. And as common wisdom and [[Code Against Interfaces, Not Implementations|Chapter 8]] advice it is preferable to ''code against interfaces and not the implementation''. The [[Code Against Interfaces, Not Implementations|Chapter 8]] explains that this old good advice can have various meanings and take multiple forms. One of such forms is the practise of putting the implementation and interfaces sources in two distinct disk locations. This implies that the [[Java]]'s ''package private'' access modifier is useless for making these two sets of classes be friends.
+
The problem with the [[Java]] approach is that it generally dictates the files layout of your friends. Their sources need to be placed in the same directory. Many people do not like that, as this mixes the classes representing the API with the classes that provider their implementation. This is not perfect. Common wisdom and also [[Code Against Interfaces, Not Implementations|Chapter 8]] advice, that it is preferable to ''code against interfaces and not the implementation''. The [[Code Against Interfaces, Not Implementations|Chapter 8]] explains that this old good advice can have various meanings and take multiple forms. One of such forms is the practise of putting the implementation and interfaces sources in two distinct disk locations. This is exactly against the requirements of the [[Java]]'s ''package private'' access modifier, making it useless for establishing friendship between distinct API and implementation packages.
This often leads people to open the APIs up and use '''public''' or '''protected''' modifiers, sometimes annotating the method with a javadoc note ''do not call me, I am part of the implementation''. This is unfortunate as it pollutes the APIs with useless implementation details, distracts the API users and potentially creates security holes in the API.
This often leads people to open the APIs up and use '''public''' or '''protected''' modifiers, sometimes annotating the method with a javadoc note ''do not call me, I am part of the implementation''. This is unfortunate as it pollutes the APIs with useless implementation details, distracts the API users and potentially creates security holes in the API.

JaroslavTulach at 11:40, 24 October 2008 - 2008-10-24 11:40:46

←Older revision Revision as of 11:40, 24 October 2008
Line 1: Line 1:
-
wikipedia::Object-oriented_programming_language|object oriented languages]] offer some kind of [[encapsulation]], which often takes form of having '''public''', '''protected''' and '''private''' access modifiers. Indeed, designers soon found that this is not enough and as such [[C++]] has ''friend'' constructs and [[Java]] adds additional ''package private'' access type.
+
Common [[wikipedia::Object-oriented_programming_language|object oriented languages]] offer some kind of [[encapsulation]], which often takes form of having '''public''', '''protected''' and '''private''' access modifiers. Indeed, designers soon found that this is not enough and as such [[C++]] has ''friend'' constructs and [[Java]] adds additional ''package private'' access type.
The problem with the [[Java]] approach is that it generally dictates the files layout of your friends. They need to be placed in the same directory. Many people do not like that, as this mixes the classes representing the API with the classes that implement them. And as common wisdom and [[Code Against Interfaces, Not Implementations|Chapter 8]] advice it is preferable to ''code against interfaces and not the implementation''. The [[Code Against Interfaces, Not Implementations|Chapter 8]] explains that this old good advice can have various meanings and take multiple forms. One of such forms is the practise of putting the implementation and interfaces sources in two distinct disk locations. This implies that the [[Java]]'s ''package private'' access modifier is useless for making these two sets of classes be friends.
The problem with the [[Java]] approach is that it generally dictates the files layout of your friends. They need to be placed in the same directory. Many people do not like that, as this mixes the classes representing the API with the classes that implement them. And as common wisdom and [[Code Against Interfaces, Not Implementations|Chapter 8]] advice it is preferable to ''code against interfaces and not the implementation''. The [[Code Against Interfaces, Not Implementations|Chapter 8]] explains that this old good advice can have various meanings and take multiple forms. One of such forms is the practise of putting the implementation and interfaces sources in two distinct disk locations. This implies that the [[Java]]'s ''package private'' access modifier is useless for making these two sets of classes be friends.