ViewLoader is now modeled as a stateless singleton and injected into all
components (usually controllers) that need it. This is as opposed to the
prior situation in which a ViewLoader was instatiated every time view
loading was required. This was an understerstandable approach, given
that FXMLLoader (which ViewLoader wraps) assumes the same
construction-per-use approach, but it is nevertheless problematic.
- Return Item tuple from ViewLoader#load.
This avoids the need to call ViewLoader#load followed by individual
calls to get the view and then the controller, as this requires
mutable state to be held in the ViewLoader (which is now a shared
singleton injected throughout the application). The previous approach
is (a) confusing and (b) could create problems in a multithreaded
environment. While (b) is unlikely in our case, the new approach is
still clearer anyway.
- Refactor ViewLoader#load to accept URL vs FxmlResource.
This decouples the ViewLoader abstraction away from the
Navigation.Item / FxmlResource abstraction completely.
Changes to MainViewCB
---------------------
This is a siginificant restructuring of the main controller in the
system and suggests a number of ideas and practices that should be
applied when refactoring the rest of the controllers or designing new
ones. UI code is inherently verbose; as such, the best we can do is to
structure a controller such as MainViewCB in a way that minimizes the
verbosity as much as possible and focuses on making what is happening as
clear as possible. That's why (as is described further below), almost
everything important now happens in the #initialize method. A major goal
of this change is that developers are able to look at MainViewCB and
read its #initialize method like a script. Indirections to other methods
are minimized as much as possible. The primary focus is on readability
(and therefore maintainability).
These changes began as an effort to substitute a mocked-out "backend",
i.e. bitcoin and p2p infrastructure, such that the application could
be run as quickly as possible, without the need for network
sychronization, bootstrapping, etc, for the purposes of UI development
and testing. Trying to make that change naturally evolved into this set
of refactorings. So at this point, MainViewCB is still "hard-wired" to
live bitcoin and tomp2p backends, but changing that, i.e. providing
mocked-out backends will be that much easier and clearer to accomplish
now.
Specifics:
- Use public vs. private contstructor. This allows for the possibility
of unit testing, avoids spurious warnings in the IDE, and generally
adheres to the principle of least surprise.
- Orchestrate creation and composition of components within the
#initialize method. This avoids the need for member fields almost
entirely.
- Extract and delegate to private methods from #initialize only where
it helps readibility. In general, this change assumes that initialize
should be "where the action is": if the layout of a particular view
is complex, then deal with that complexity directly within the
#initialize method. However, if the creation of a given component is
particularly verbose--for example the creation of the splash screen,
then extract a #createSplashScreen method that returns a VBox. The
same approach has been applied in extracting the
#createBankAccountComboBox, #applyPendingTradesInfoIcon and
#loadSelectedNavigation methods.
- Extract the NavButton member class to cleanly encapsulate what it
means to be a ToggleButton on the Bitsquare application navigation.
This approach is similar to the MenuItem class in
AccountSettingsViewCB.
- Use "double-brace initialization" syntax for JavaFX components
where appropriate, e.g.:
HBox rightNavPane =
new HBox(accountComboBox, settingsButton, accountButton) {{
setSpacing(10);
setRightAnchor(this, 10d);
setTopAnchor(this, 0d);
}};
This approach, while typically rarely used, is an especially
appropriate fit for JavaFX UI components, as the the allows for both
maximum concision and clarity. Most JavaFX components are configured
through a combination of constructor parameters and setter method
invocations, and this approach allows all of them to happen at
construction/initialization time.
- Remove class section comments. In general--and as @mkarrer and I have
discussed--these `////...` blocks shouldn't be necessary going
forward. The goal is classes that are as small and focused as they
can be, and they should be self-documenting to the greatest degree
possible.
- Remove empty lifecycle methods from the ViewCB superclass.
- Remove Profiler statements. These are fine for specific debugging
sessions, but should otherwise be removed for normal use.
Changes to Navigation.Item
--------------------------
These changes to the Navigation.Item enum were made in support of the
refactorings above, particularly in support of the newly extracted
NavButton class being as concise to construct as possible.
- Introduce Navigation.Item#getDisplayName
Push navigation button titles, such as "Overview" for HOME, "Buy BTC"
for BUY, etc. into the Navigation.Item enum itself. This can later be
refactored to support I18N, e.g. by embedding a message label instead
of the actual english word. Not all Navigation items have a display
name yet (and it may or may not make sense for them all to have one).
The default value is "NONE".
- Use AtomicBoolean vs. SimpleBooleanProperty in TomP2PTests to avoid
use of javax.* classes where they aren't otherwise necessary.
- Reformat code globally to eliminate trailing whitespace and fix
indentation
- Optimize imports globally to eliminate unused imports
* cbeams:
Polish FeePolicy
Use BitcoinNetwork vs. BitcoinJ's NetworkParameters
Use #ofType in commandline parsing for type safety
Introduce customized JOptCommandLinePropertySource
Expose network information to GUI cleanly
Conflicts:
src/main/java/io/bitsquare/msg/tomp2p/TomP2PNode.java
- Convert static fields to final instance fields
- Remove commented code
- Rethrow any AddressFormatException as a BitsquareException instead of
logging and returning null (doing so would cause NPEs in BitcoinJ
internals).
BitcoinNetwork now supports a #getParameters method that returns the
BitcoinJ NetworkParameters instance associated with the given
BitcoinNetwork enum label (e.g. TESTNET.getParameters() returns
TestNet3Params, etc).
BitcoinModule#BITCOIN_NETWORK_KEY and #DEFAULT_BITCOIN_NETWORK have been
moved to BitcoinNetwork#KEY and BitcoinNetwork#DEFAULT respectively.
Customzing the bitcoin network to use on the command line has been
improved. Values may be upper or lower case (e.g. "testnet", "TESTNET"),
and the value passed is converted to the correct BitcoinNetwork enum
value with the new EnumValueConverter class.
Finally, a BitcoinNetwork instance is now made available for injection
by BitcoinModule as opposed to binding a NetworkParameters instance. All
injection targets (constructors) throughout the codebase have been
updated to reflect this change, and the result is cleaner, enum-based
processing everywhere possible. And where it's necessary to drop down to
BitcoinJ's NetworkParameters, that's easy to do by calling
BitcoinNetwork#getParameters.
This temporary subclass introduces the same change proposed in
spring-projects/spring-framework#693, and should be removed when that
pull request is merged and made available.
This commit introduces io.bitsquare.network.ClientNode--an interface
whose name and structure will surely change--as a simplistic abstraction
over TomP2PNode that allows for exposing information to the "Network"
tab of the Preferences section of the GUI without actually requiring the
injection of TomP2PNode and other tomp2p internals into the GUI layer.
Changes to 'network' and 'msg' packages:
----------------------------------------
- Move ConnectionType enum from test into main tree, and expose
ClientNode#getConnectionType.
- Both ClientNode and TomP2P are now available for injection. Both
types are bound to the same TomP2P singleton instance. Note
especially how NetworkPreferencesViewCB now receives a ClientNode
instead of a TomP2PNode.
- Restore package-private visibility to BootstrappedPeerFactory
- Remove no longer necessary TomP2PNode#getPeerDHT
- Expose getter for BootstrappedPeerFactory#bootstrapState
Changes to 'gui' package:
-------------------------
- NetworkPreferencesViewCB has been simplified. All no-op methods have
been removed, and the class now simply implements JavaFX's
Initializable interface as opposed to Bitsquare's own ViewCB
hierarchy, because the latter is not actually necessary (no caching
is required for the data handled by this controller, etc.
- In order to make the above possible, PreferencesViewCB now tolerates
adding non-ViewCB child controllers.
- NetworkPreferencesPM has been removed (perhaps temporarily), in an
experiment to see "just how simple" CB controller classes can be.
- Text fields in NetworkPreferencesView have been renamed.
Notes:
------
The data that now shows up in the "Network" tab is no longer formatted
as it once was; values are essentially nothing more than their #toString
representations. Again, this can be tweaked further, but leaving things
in this raw state provides an opportunity to discuss the current
presentation model approach, ViewCB hierarchy, etc.