JaroslavTulach: /* Mutable Capabilities */ - 2013-06-09 07:06:54

Mutable Capabilities

←Older revision Revision as of 07:06, 9 June 2013
Line 43: Line 43:
You are designing an API for an object whose capabilities are actually mutable. Listening for a particular type in a Lookup is much less code, and much clearer, than defining a bunch of event types, listener classes and addThisListener(), addThatListener(). Example: In the Java Card modules, there is a class Card. A Card has a lookup. Now a card might be a physical device plugged into your computer. Or it might be a virtual card definition used by an emulator for testing. A
You are designing an API for an object whose capabilities are actually mutable. Listening for a particular type in a Lookup is much less code, and much clearer, than defining a bunch of event types, listener classes and addThisListener(), addThatListener(). Example: In the Java Card modules, there is a class Card. A Card has a lookup. Now a card might be a physical device plugged into your computer. Or it might be a virtual card definition used by an emulator for testing. A
-
virtual card has capabilities like Stop, Start and Resume. When you call StartCapability.start(), the StartCapability disappears from the Card's lookup and a StopCapability appears. But if it is a physical card, Start and Stop make no sense whatsoever - so for a real card they are not there. Other capabilities, such as PortProvider, which will tell you what TCP ports to use to send code to, attach a debugger to, etc., are present for both virtual cards and some real cards, if HTTP is the mechanism to deploy code to them - but other cards may have you run a native executable to deploy code and use no ports. So PortProvider is another optional capability.
+
virtual card has capabilities like Stop, Start and Resume. When you call StartCapability.start(), the StartCapability disappears from the Card's lookup and a StopCapability appears. But if it is a physical card, Start and Stop make no sense whatsoever - so for a real card they are not there. Other capabilities, such as PortProvider, which will tell you what TCP ports to use to send code to, attach a [[debugger]] to, etc., are present for both virtual cards and some real cards, if HTTP is the mechanism to deploy code to them - but other cards may have you run a native executable to deploy code and use no ports. So PortProvider is another optional capability.
Note that you can add typing to [[Lookup]]-based [[API]]s if you find it useful or it makes your API easier (with Find Usages or [[Javadoc]]) to use. In org.netbeans.modules.javacard.spi.Card, in fact, there is
Note that you can add typing to [[Lookup]]-based [[API]]s if you find it useful or it makes your API easier (with Find Usages or [[Javadoc]]) to use. In org.netbeans.modules.javacard.spi.Card, in fact, there is
Line 52: Line 52:
Perhaps there are other scenarios that I have missed for when Lookup makes sense, but I think those 4 cover most of the typical cases. If you're not doing something like that - if using Lookup adds complexity to your code without adding needed flexibility or future-proofing - then it's the wrong tool for the job.
Perhaps there are other scenarios that I have missed for when Lookup makes sense, but I think those 4 cover most of the typical cases. If you're not doing something like that - if using Lookup adds complexity to your code without adding needed flexibility or future-proofing - then it's the wrong tool for the job.
-
 
=== Overuse of [[Lookup]] ===
=== Overuse of [[Lookup]] ===
Sometimes people call [[Lookup]] ''magical bag''. The pejorative flavor of the nickname is based on observation that you can put your hand in it and pray to find the object you are seeking for. Sometimes people believe there shall be a better way. Yes, in many cases there is. [[Lookup]] is not handy for everything. It is basically a tool to implement a [[teleinterface]]s. In case a [[teleinterface]] is not what you want (like in case of [[CumulativeFactory]]), you'd rather prefer type safety and design proper [[API]] without ''magical bag'' - aka [[Lookup]]. More about that in [[Chapter 7]].
Sometimes people call [[Lookup]] ''magical bag''. The pejorative flavor of the nickname is based on observation that you can put your hand in it and pray to find the object you are seeking for. Sometimes people believe there shall be a better way. Yes, in many cases there is. [[Lookup]] is not handy for everything. It is basically a tool to implement a [[teleinterface]]s. In case a [[teleinterface]] is not what you want (like in case of [[CumulativeFactory]]), you'd rather prefer type safety and design proper [[API]] without ''magical bag'' - aka [[Lookup]]. More about that in [[Chapter 7]].

JaroslavTulach at 05:02, 6 December 2012 - 2012-12-06 05:02:55

←Older revision Revision as of 05:02, 6 December 2012
Line 2: Line 2:
* See {{NB|org-openide-util-lookup|org/openide/util|Lookup}}
* See {{NB|org-openide-util-lookup|org/openide/util|Lookup}}
-
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
+
* Install [[Ubuntu]] or [[Debian]] package '''libnb-org-openide-util-lookup-java''' (''7.0.1+dfsg1-5ubuntu2'')
 +
* Download from [[NetBeans]] [[Maven]] snapshot [http://bits.netbeans.org/netbeans/trunk/maven-snapshot/org/netbeans/api/org-openide-util-lookup/SNAPSHOT/ repository].
* Visualize [http://dev.imagejdev.org/gbh/lookup/map.htm Lookup via its mind map]
* Visualize [http://dev.imagejdev.org/gbh/lookup/map.htm Lookup via its mind map]

JaroslavTulach at 06:01, 21 April 2011 - 2011-04-21 06:01:57

←Older revision Revision as of 06:01, 21 April 2011
Line 1: Line 1:
[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
-
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
+
* See {{NB|org-openide-util-lookup|org/openide/util|Lookup}}
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
* Visualize [http://dev.imagejdev.org/gbh/lookup/map.htm Lookup via its mind map]
* Visualize [http://dev.imagejdev.org/gbh/lookup/map.htm Lookup via its mind map]
Line 9: Line 9:
This greatly simplifies final assembly and deployment of the application. It is enough to drop the [[JAR]]s with an implementation available in the system and all the pieces can work suddenly cooperate by mutually discovering themselves via ''Lookup.getDefault().lookup(...)''.
This greatly simplifies final assembly and deployment of the application. It is enough to drop the [[JAR]]s with an implementation available in the system and all the pieces can work suddenly cooperate by mutually discovering themselves via ''Lookup.getDefault().lookup(...)''.
-
On the other hand, looking from a local point of view, there can be many ''pools'' to fish for an interface. Almost any object can implement [http://hudson.apidesign.org/hudson/job/lookup/org.apidesign$lookup/javadoc/org/openide/util/Lookup.Provider.html Lookup.Provider] interface and thus give access to its adaptable features to everyone.
+
On the other hand, looking from a local point of view, there can be many ''pools'' to fish for an interface. Almost any object can implement {{NB|org-openide-util-lookup|org/openide/util|Lookup.Provider}} interface and thus give access to its adaptable features to everyone.
Using the same interface to play two different roles ([[Injection|component injection]] and [[Adaptable]] pattern) shows the common properties of both. The [[Lookup]] can serve as a assembly language to provide ''pool'' of objects to use during real [[Dependency Injection]]. The [[LookupAndSpring|bridge between Lookup and Spring]] provides more details about this area.
Using the same interface to play two different roles ([[Injection|component injection]] and [[Adaptable]] pattern) shows the common properties of both. The [[Lookup]] can serve as a assembly language to provide ''pool'' of objects to use during real [[Dependency Injection]]. The [[LookupAndSpring|bridge between Lookup and Spring]] provides more details about this area.

JaroslavTulach at 08:51, 16 April 2011 - 2011-04-16 08:51:06

←Older revision Revision as of 08:51, 16 April 2011
Line 1: Line 1:
-
<math>Insert formula here</math>[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
+
[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]

JaroslavTulach at 16:20, 10 January 2011 - 2011-01-10 16:20:25

←Older revision Revision as of 16:20, 10 January 2011
Line 1: Line 1:
-
[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
+
<math>Insert formula here</math>[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
 +
* Visualize [http://dev.imagejdev.org/gbh/lookup/map.htm Lookup via its mind map]
The basic idea, in its [[ServiceLoader]] incarnation is that it is enough to compose an application from various [[JAR]] files and let these [[JAR]] files communicate. This is achieved by defining well-known location inside the [[JAR]] file ''META-INF/services/nameoftype'' that is read from all available libraries [[JAR]]s on the classpath.
The basic idea, in its [[ServiceLoader]] incarnation is that it is enough to compose an application from various [[JAR]] files and let these [[JAR]] files communicate. This is achieved by defining well-known location inside the [[JAR]] file ''META-INF/services/nameoftype'' that is read from all available libraries [[JAR]]s on the classpath.

JaroslavTulach at 10:04, 24 December 2010 - 2010-12-24 10:04:22

←Older revision Revision as of 10:04, 24 December 2010
Line 2: Line 2:
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
-
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform11/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
+
* Download and unzip [http://bits.netbeans.org/dev/nightly/latest/uc/platform/org-openide-util-lookup.nbm org-openide-util-lookup.zip]
The basic idea, in its [[ServiceLoader]] incarnation is that it is enough to compose an application from various [[JAR]] files and let these [[JAR]] files communicate. This is achieved by defining well-known location inside the [[JAR]] file ''META-INF/services/nameoftype'' that is read from all available libraries [[JAR]]s on the classpath.
The basic idea, in its [[ServiceLoader]] incarnation is that it is enough to compose an application from various [[JAR]] files and let these [[JAR]] files communicate. This is achieved by defining well-known location inside the [[JAR]] file ''META-INF/services/nameoftype'' that is read from all available libraries [[JAR]]s on the classpath.

JaroslavTulach: /* System-level-decoupling */ - 2010-01-25 08:28:08

System-level-decoupling

←Older revision Revision as of 08:28, 25 January 2010
Line 18: Line 18:
==== System-level-decoupling ====
==== System-level-decoupling ====
-
You provide some interface. Some other module will actually implement the interface. You want modules to be able to use your [[API]], without caring who implements it, just that some implementation is there. Example: The status line.
+
You provide some interface and expose it via [[Injectable Singleton]]. Some other module will actually implement the interface. You want modules to be able to use your [[API]], without caring who implements it, just that some implementation is there. Example: The status line.
<source lang="java">
<source lang="java">
StatusDisplayer.getDefault()
StatusDisplayer.getDefault()

213.61.134.194 at 17:15, 20 January 2010 - 2010-01-20 17:15:14

←Older revision Revision as of 17:15, 20 January 2010
Line 1: Line 1:
-
[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queries for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
+
[[Lookup]] is a library that provides [[API]] that unifies [[Injection|component injection]] with [[adaptable]] pattern. It is based on long time [[JDK]] standard for registering instances of services in [[JAR]] files which has been formalized as [[ServiceLoader]] in [[JDK]] 6. [[Lookup]] extends this area and allows ''local pools'' of objects that can be queried for certain capability. [[Lookup]] is also suited for dynamic environment as it supports notification of changes. [[Lookup]] bridges the classical [[Injection|injection]] pattern with local [[adaptable]] pattern.
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]
* See [http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/ Javadoc]

JaroslavTulach: /* Overuse of Lookup */ - 2010-01-20 08:55:54

Overuse of Lookup

←Older revision Revision as of 08:55, 20 January 2010
Line 11: Line 11:
Using the same interface to play two different roles ([[Injection|component injection]] and [[Adaptable]] pattern) shows the common properties of both. The [[Lookup]] can serve as a assembly language to provide ''pool'' of objects to use during real [[Dependency Injection]]. The [[LookupAndSpring|bridge between Lookup and Spring]] provides more details about this area.
Using the same interface to play two different roles ([[Injection|component injection]] and [[Adaptable]] pattern) shows the common properties of both. The [[Lookup]] can serve as a assembly language to provide ''pool'' of objects to use during real [[Dependency Injection]]. The [[LookupAndSpring|bridge between Lookup and Spring]] provides more details about this area.
 +
 +
=== Tim Boudreau on [[Lookup]] ===
 +
 +
In a response to question about appropriate use of [[Lookup]], Tim provided following answers.
 +
 +
==== System-level-decoupling ====
 +
 +
You provide some interface. Some other module will actually implement the interface. You want modules to be able to use your [[API]], without caring who implements it, just that some implementation is there. Example: The status line.
 +
<source lang="java">
 +
StatusDisplayer.getDefault()
 +
</source>
 +
returns some implementation of ''StatusDisplayer''. In [[NetBeans]] typically it is provided by the window system. But I once wrote an implementation that would instead hide the status bar and instead show the message in a translucent popup that
 +
appears over the main window. That would not have been possible if all code that wanted to display status messages was tied at compile-time to the implementation class provided by the window system.
 +
 +
==== Designing an API for a not-well-defined problem space ====
 +
 +
 +
For Example the ''Project.getLookup()''. In the case of projects, when that [[API]] was designed, the only things that could be known for sure about a project were that:
 +
* A project is a directory
 +
* For any file, there will be zero or one projects that own that file
 +
Designing a Project API that would provide for everything C/[[C++]], [[Ruby]], [[Java]], DocBook, [[HTML]], Web, J2EE, J2ME, etc. projects (this had been tried) would end up with something bloated and filled with functionality that any random client would never use - a very noisy, hard-to-use [[API]]. Since in that case the requirements were not and could not be known, the [[lookup]] pattern made it possible to create an API and let clients define additional APIs (like ClassPathProvider for Java projects, which would make no sense in a DocBook project), and provide client access to them
 +
through the project's [[Lookup]].
 +
 +
==== Granular decoupling ====
 +
 +
The uses of [[Lookup]] in Node and TopComponent: Here, you have some [[API]] type. You make it available in the Lookup of files of a certain type. You don't necessarily know all the ways your UI will change in the future. Other modules want to add actions (to popup menus, toolbars, whatever) that can operate on your type. Those actions should be enabled whenever the selection contains one (or more) of your object. By writing actions sensitive to your type in the global selection lookup (Utilities.actionsGlobalContext()), no rewrite of those actions is required if, at some point, you write a new window component that shows, say, virtual files or some random tree of objects that contain your type.
 +
 +
==== Mutable Capabilities ====
 +
 +
You are designing an API for an object whose capabilities are actually mutable. Listening for a particular type in a Lookup is much less code, and much clearer, than defining a bunch of event types, listener classes and addThisListener(), addThatListener(). Example: In the Java Card modules, there is a class Card. A Card has a lookup. Now a card might be a physical device plugged into your computer. Or it might be a virtual card definition used by an emulator for testing. A
 +
virtual card has capabilities like Stop, Start and Resume. When you call StartCapability.start(), the StartCapability disappears from the Card's lookup and a StopCapability appears. But if it is a physical card, Start and Stop make no sense whatsoever - so for a real card they are not there. Other capabilities, such as PortProvider, which will tell you what TCP ports to use to send code to, attach a debugger to, etc., are present for both virtual cards and some real cards, if HTTP is the mechanism to deploy code to them - but other cards may have you run a native executable to deploy code and use no ports. So PortProvider is another optional capability.
 +
 +
Note that you can add typing to [[Lookup]]-based [[API]]s if you find it useful or it makes your API easier (with Find Usages or [[Javadoc]]) to use. In org.netbeans.modules.javacard.spi.Card, in fact, there is
 +
<source lang="java">
 +
public <T extends ICardCapability> T getCapability(Class<T> type);
 +
</source>
 +
which delegates to Lookup but guarantees the return value is a subtype of something you can search on. I don't recommend that for all situations (part of the birth of Lookup was that Node.getCookie() returned something that implemented the marker interface Node.Cookie, and for things that wanted lookup-like functionality but had no connection to Nodes whatsoever, it made no sense to make them drag around a JAR with the Nodes API just for a marker interface). But in restricted situations, it can make an API more usable.
 +
 +
Perhaps there are other scenarios that I have missed for when Lookup makes sense, but I think those 4 cover most of the typical cases. If you're not doing something like that - if using Lookup adds complexity to your code without adding needed flexibility or future-proofing - then it's the wrong tool for the job.
 +
=== Overuse of [[Lookup]] ===
=== Overuse of [[Lookup]] ===
Sometimes people call [[Lookup]] ''magical bag''. The pejorative flavor of the nickname is based on observation that you can put your hand in it and pray to find the object you are seeking for. Sometimes people believe there shall be a better way. Yes, in many cases there is. [[Lookup]] is not handy for everything. It is basically a tool to implement a [[teleinterface]]s. In case a [[teleinterface]] is not what you want (like in case of [[CumulativeFactory]]), you'd rather prefer type safety and design proper [[API]] without ''magical bag'' - aka [[Lookup]]. More about that in [[Chapter 7]].
Sometimes people call [[Lookup]] ''magical bag''. The pejorative flavor of the nickname is based on observation that you can put your hand in it and pray to find the object you are seeking for. Sometimes people believe there shall be a better way. Yes, in many cases there is. [[Lookup]] is not handy for everything. It is basically a tool to implement a [[teleinterface]]s. In case a [[teleinterface]] is not what you want (like in case of [[CumulativeFactory]]), you'd rather prefer type safety and design proper [[API]] without ''magical bag'' - aka [[Lookup]]. More about that in [[Chapter 7]].

JaroslavTulach: /* Overuse of Lookup */ - 2010-01-19 20:10:24

Overuse of Lookup

←Older revision Revision as of 20:10, 19 January 2010
Line 14: Line 14:
=== Overuse of [[Lookup]] ===
=== Overuse of [[Lookup]] ===
-
Sometimes people call [[Lookup]] ''magical bag''. The pejorative flavor of the nickname is based on observation that you can put your hand in it and pray to find the object you are seeking for. Sometimes people believe there shall be a better way. Yes, in many cases there is. [[Lookup]] is not handy for everything. It is basically a tool to implement a [[teleinterface]]s. In case a [[teleinterface]] is not what you want (like in case of [[CumulativeFactory]]), you'd rather prefer type safety and design proper [[API]] without ''magical bag'' - aka [[Lookup]].
+
Sometimes people call [[Lookup]] ''magical bag''. The pejorative flavor of the nickname is based on observation that you can put your hand in it and pray to find the object you are seeking for. Sometimes people believe there shall be a better way. Yes, in many cases there is. [[Lookup]] is not handy for everything. It is basically a tool to implement a [[teleinterface]]s. In case a [[teleinterface]] is not what you want (like in case of [[CumulativeFactory]]), you'd rather prefer type safety and design proper [[API]] without ''magical bag'' - aka [[Lookup]]. More about that in [[Chapter 7]].