Comments (5)
A better alternative to the ParameterAssembler visitor concept in 17e5a01 might be to just put the Create/Restore functions in each DTO with abstract Create/Restore on the ParameterDTO so the ParameterAssembler just calls the objects func and returns that. It's still within the realms of concern for the DTO to do this.
Since one of the main reasons for the visitor pattern is to add additional functionality without requiring changes to the types it operates on, and I really don't need to be adding any more functionality and it can be solved using standard polymorphism, then just use standard polymorphism.
from dbqf.
I started to investigate polymorphism for restore/create but it starts coming unstuck when either process requires further knowledge that is not the concern of the DTO being created (e.g. restoring a FieldPath needs a FieldPathAssembler which has its own requirements and is definitely nothing to do with a ParameterDTO).
After beginning to implement the Visitor pattern in 1090f72 it's also become evident this is a flawed approach. The Visitor pattern has some serious limitations.
- It successfully removes the concern of how to transform data beyond an individual parameter's concern, but starts falling down when you need to do something with the new objects. Either using the visitor object to store state of the conversion due to the traditional
void Visit
signature, or muddying the contract withIParameter Visit
which begins to erode the reuseability of the pattern. Plus the data structure follows the composite pattern, meaning we have an unknown depth of data structure making the state difficult to manage. - The Restore process can implement
Accept
/Visit
behaviour on the DTO's and it works well, but when it comes to the Create process the visit pattern needs to exist onIParameter
. STOP! This means embedding the visitor pattern into the core library and providing concrete interfaces with all known types defined for the visitor. This destroys extensibility as any additional parameters a user wants to add can't be added to the compiled interface.
Thinking of the problem trying to be solved is this: we're trying to serialize an IParameter composite type to XML.
- We could implement our own serializer to control every aspect of how the XML is generated.
- We could use DTO's to transform and simplify the data structure and use the built-in serializer.
Using our own serializer limits us to a specific implementation of serialization (in this case, XML). We'd have to rewrite all this code if we were to serialize to another format.
If we use DTO's we separate the concern of transforming the data to persisting it which is good, but how do we cleanly manage the transformations?
- Have an assembler that has a big conditional block to transform each and every type.
- Pros: it's simple.
- Cons: source of bugs, runtime type checking, inflexible, hard to maintain.
- Have an assembler using the visitor pattern to transform
- Pros: compile time checking, no conditionals
- Cons: everything above (high coupling, poor handling of composite data structures, lack of extensibility)
- Use the chain of responsibility pattern for the assembler
- Pros: modular handling of transformations, extensible
- Cons: runtime type checking
For now, we'll attempt the chain of responsibility pattern. The caveat of runtime type-checking is unfortunate, but it's easily extended (no modifying of existing classes or issues of black box behaviour from inheriting the assembler and providing further logic in create/restore), and doesn't require modification of any other classes which keeps them decoupled.
from dbqf.
After discussion, the only way to truly serialize what a user sees on screen and restore it successfully is to persist the state of the UI, not the final parameter (which undergoes parsing which transforms it's shape).
To do this, we'd need to persist:
- The type of search that was created (Preset, Standard or Advanced)
- For each element:
- The
FieldPath
that is affected - The
ParameterBuilder
in use (not the IParameter itself which comes after parsing and transformations) - The raw value from the control. TBH the control should be able to provide whatever value it likes (as long as it's serializable) because it's the one that has to deal with restoring it
- The
Issues to overcome are:
- What if the configuration changes and the
FieldPath
is no longer valid?- Tough. The only way to fix it would be to save the entire configuration for every search, but that still wouldn't overcome if the database itself has changed and the configuration itself is no longer valid.
- What if the UI changes? e.g. the default control for a list is no longer a
ComboBox
but aListBox
?- Try loading the values just like the
GetValues
/SetValues
behaviour that currently exists when the UI factory changes the control (in the Standard search control) - Don't load it
- Highlight the control as having changed (would need to persist the state of the control to know this is different)
- Try loading the values just like the
In addition, we could still persist the final parameter set just in case we can't restore the parameters to the UI. The user could be offered the option to perform the search even though it can't be displayed. Or it could be used as a sanity check to ensure the current UI and parsers generate the same search structure as the original (maybe not values though as a date field with "last week" would generate a different value if opened in the future).
from dbqf.
Add a project version number (alongside ID, configuration and connections). When a search is serialised it can save this version number too, so if either get out of date we'll know that the saved search is may no longer be valid.
from dbqf.
Merged to master at 8521d66
from dbqf.
Related Issues (20)
- Remove matrix behaviour from configuration HOT 4
- Reconfigure Castle Windsor to initialise from configuration file HOT 1
- Advanced search exception when no UIElement
- Advanced search exception when searching with between value
- Refactor Solution HOT 2
- Add to NuGet HOT 1
- Add multi-field search textbox HOT 1
- Refactor backends HOT 2
- Gtk# Implementation
- Double click edit in advanced search
- Replace parameter in advanced search
- Loading a saved advanced search fails to reinstate the correct parser
- Rename standalone assembly name
- Database permissions crash standalone application
- delegate Func defined without namespace
- Implement user-definable outputs
- Implement advanced search HOT 2
- Create control for generating a FieldPath HOT 3
- Add date picker for DateTime fields
- Implement WPF application HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dbqf.