thanks, oscar.
On 1 October 2016 at 23:34, Óscar Bou - GOVERTIS <[email protected]> wrote: > > Hi all. > > I’ve just created a Jira ticket [1] and a PR at [2] that allows to define > a Factory Method this way: > > class Concert { > > @Action(factoryMethod=true) > public Concert someAction() { > return new Concert(); > } > } > > > Factory Methods cannot return void, but no other restriction has been > applied by now (i.e., should we limit it to Domain Entities? ). > > Further work should be done at the UI level. > As a workflow example: > - When executing an Action, add a drop-down menu to show all Factory > Methods whose returned class is assignable from the param’s class. > - When clicked, launch the action’s modal dialog, overlapping the original > action invocation dialog. > - When returning from the factory method invocation to the original action > invocation dialog, if the factory method’s action : > - has been successfully executed, the returned object should be the > param’s currently selected value. > - has been cancelled, the param’s currently selected value is not changed. > > > > > HTH, > > Oscar > > [1] https://issues.apache.org/jira/browse/ISIS-1509 > [2] https://github.com/apache/isis/pull/55/files > > > > > > El 30 sept 2016, a las 5:07, David Tildesley <[email protected]> > escribió: > > Hi All, > > Imho: > > Putting the "don't do CRUD" principle spin on this: Isn't it just a matter > of allowing a "Concert" component (I call it component since it will have > several objects that are associated with the primary moment-interval) > instance to be "built up" until it can be "published"? All you need is a > "canPublish()" method returning a boolean that does all the necessary > checks to ensure all the required bits and bobs are in place before > "publishing" it (for want of a better term). Why are you wanting to create > a rod for you own back by having database constraints to enforce business > logic when you can enforce the constraints in logic in your code with more > flexibility? I may be wrong, but I think the Naked Object model would force > you take this approach because you are only allowed to "see" domain objects > in the viewer. Use of view models will tend to take you in the other > direction - caution needed. Conflating "view" aspects with "domain" aspects > will make the situation worse. > > Next make sure you have firmly in your mind the separation of UI concerns > from domain layer concerns - don't conflate them. If you need to create > some view models to build aggregate forms or a wizard - because that is > what your users demand just remember the separation of concerns principle > - view models are UI, not domain layer and they will tend to cause you to > compromise the domain layer/model if you are not fastidious about this. > > By the way, it is next to impossible to have this discussion without a > proper domain model available - if there is no domain model available then > you are already traveling an unsound path. > > Regards, > > David. > > On 30-Sep-16 12:37 PM, Stephen Cameron wrote: > > Hi Martin, > > Just a few thoughts in response inline. > > On Fri, Sep 30, 2016 at 12:51 AM, Martin <[email protected]> > wrote: > > Thanks all for your replies and your input. > > The DDD book was actually one of the books I bought many years ago and > enjoyed reading a lot. I still recommend it to friends and colleagues. > > :) Which probably led you to trying Apache Isis? > > I gave Stephens idea a second thought and tried out this approach today. > For the association of more complex objects, like let's say a > ConcertLocation which cannot be created from within the Concert dialogue > there is a Fixture creating a dummy placeholder ConcertLocation object, > which can be selected instead, and the Concert entity has an action to > create a new ConcertLocation, so that things can be corrected after > creation. > > I'm don't think this is the best approach to take, if a Concert must have a > concert location then offer the user two options in the Concert dialogue, a > list of existing ConcertLocations and a String parameter to (at least) name > a new one if the one of interest does not pre-exist. A validate method for > the create action can check that one of these but not both is > selected/filled. That was Dan's suggestion I think. > > If the problem is that there are so many mandatory properties for a Concert > the Concert 'create' action gets to become a big list of parameters, and > one that is confusing to 'naive' users, which I don't Apache Isis being a > good fit for anyway. There might be a case for designing a ConcertBuilder > domain class, this is just used to collect data for then creating a new > valid Concert. Such a ConcertBuilder could be a state-machine maybe, it has > a series of Actions that are enabled or disabled based on current state? > > I will still have to come up with a way to highlight/color fields that > reference placeholder objects (identified by name or by a flag) to make it > clear in the UI that something still needs to be done. This does the trick > for a few cases where there the next level object only has trivial > properties or associations to already existing objects. > > To address how to draw attention of the users to replacing placeholders > with real objects a possible approach would be to have special query for > the placeholder objects to see which other objects reference them, maybe > thus proposing a set of ToDos/problems to the user on the dashboard that > need to be addressed. Such as: there are currently three concerts > referencing the dummy/placeholder location, please go look at them and > correct that. One could probably construct a business rule from that to > check for overall validity of an object tree. If any of the referenced > objects in the tree is a placeholder, then the path is invalid. > > There is a incode Notes module [2] that I think could be of value, this > could be used in the 'create' action to attach a note to the concert saying > that a new ConcertLocation has been created that might need further > validation. Maybe by a data-quality person. I am using this module. > > I was thinking about the distinction between static and dynamic data. There > are certainly cases when a user should not be allowed to add a new entity > to a collection, but then again I can also think about times when the data > structures that are being transferred from the real world into the system > by a user can be very complex and diverse by nature, and referenced objects > just cannot be pre-created or pre-thought of (example: a very complex > contract, or for instance a data structure that requires collaboration to > establish, and things just don't come in in the order that would be > required by the domain model to allow for validity and referential > integrity at all time, so that you need to create "proxy" objects as > placeholders). > > I think my distinction is misunderstood, if something complex is modelled > in the domain model it's inherently part of the model, the source of the > data is irrelevant. Maybe static vs dynamic is the wrong wording, perhaps > its best to think of the model as having a boundary (models are by > definition simplifications), and some things outside the boundary are still > of interest but are represented inside the model just by identifiers. [In > my ideal world more detail on such things could be resolved in real time > via a web-services, hypermedia essentially, so the boundary is not that > distinct]. > > I'm now trying to think of ways to improve performance of my app, I'll look > at caching, this distinction seems useful here too, things that are dynamic > aren't good candidates for caching whereas things that are static are. This > might be a first pass caching strategy, then there might be specific > dynamic objects that are accessed by lots of users, but to cache them needs > more logic. > > I found an issue in my app that presenting a list of choices to the user > was very slow, as I assume Apache Isis was building all the complete > objects, essentially just to be able to create the title of each to show in > the UI. So to get around this I created an "ParticipantIdentity" ViewModel > class (based on a database view) that just has the title and primary key > integer as properties, it is used in the 'choices' method for the > "Participant" action parameter, and once a choice has been made the action > resolves just one real Participant object to use. > > I would also be very curious to see a quick code example from Oscar, since > that seems to address my issue/request very well, and an annotation would > give the opportunity to make a case by case decision on when to allow this > in the domain and when not. > > Thanks and regards, > Martin > > > > > > > > > > > > > On Thu, Sep 29, 2016 at 4:24 PM, Dan Haywood <[email protected] > wrote: > > could you sketch a quick code example, eg with Martin's original Concert > example... guess I'm being dumb, but I don't quite get it. > > thx > Dan > > On 29 September 2016 at 09:20, Óscar Bou - GOVERTIS <[email protected]> > wrote: > > Hi, Dan. > > In our case it’s a top level annotation with any params. > > But probably on Isis it should be part of the @Action annotation. > > Important here is that, despite seeming that factory methods should have > always “non-idempotent” semantics, if before creating the new instance, > > you > > verify it does not previously exists in the database and not create > > (only > > update) if so - an UPSERT operation - it would become an idempotent > > factory > > method. > > So we cannot infer from being a factory method that it’s an idempotent > > or > > non-idempotent action. > > We usually prefer non-idempotent actions as factory methods, but we have > also some actions being both an idempotent and factory methods. > > > Regards, > > Oscar > > > > El 28 sept 2016, a las 20:56, Dan Haywood <[email protected] > escribió: > > Hi Oscar, > thanks for this. Could you sketch out what that might look like in > > terms > > of (an extension to) Isis' annotations? > Cheers > Dan > > > On 28 September 2016 at 18:24, Óscar Bou - GOVERTIS <[email protected] > wrote: > > In our custom viewer, we have a specific annotation to identify Factory > Methods. > We infer from the returned type the associated class they are able to > instantiate. > > That way, we can draw a drop-down menu associated with a button, > > present > > in any param requiring an entity of that class. > When a factory method menu is selected, the modal dialog associated > > with > > that factory method action is shown, and if executed successfully, > > when the > > modal dialog closes, the params combos are refreshed (if not > > dinamically > > loaded at drop down). > > I think that’s Martin’s initial requirement. > > It’s also a quite generic solution. > > HTH, > > Oscar > > > > El 28 sept 2016, a las 16:02, Stephen Cameron < > [email protected]> escribió: > > Hi, > > I'll briefly give my experiences, but first I have to admit that I've > need > to break some old habits, but I am still learning. I think the best way > to > think about Isis is in the OO manner of object methods being messages, > that > in triggering an action you are telling the object to do something, by > passing a message. Do have a look at Estatio as a complex Isis > Application, > lots of action (buttons) used in places where they are most > useful/logical/intuitive. > > My current idea on developing with Isis is to forget about the UI > initially, and instead focus on creating fixtures and integration > > tests. > > My 'messages' start out as XML data and then this gets parsed into the > domain model in the fixtures, and the integration test is simply > > checking > > that what was in the XML hierarchical structure is now in Java objects > and > hence the database. > > This is not a proven approach, but it does seem to me to have promise > > as > > a > good way to build a solid foundation. The general test-driven approach > > is > > what most would recommend, but my angle is that the system UI will > > evolve > > easily from this evolving domain model foundation, as your > > understanding > > increases, in an agile way. I can explain this in more detail if you > > are > > interested to try it. > > I've added some comments inline below > > On Wed, Sep 28, 2016 at 10:00 PM, Martin <[email protected] > wrote: > > Thanks for your replies. > > You are right Dan, if the location was a more complex structure than > just a > string this would of course clutter up the create dialogue of the > concert. > > Stephen: that's an interesting approach. Let's say the user creates a > concert and leaves the location empty. Then per se this is a valid > business > object (even though one attribute is missing). How would one go about > reminding/obliging the user to complete/finalize the object by going > > back > > to the concert entity page to update/create a location? > > I struggled with this issue initially, but the answer is that you > > collect > > all the mandatory requirements in one hit to create a valid object. > > Then > > when DataNucleus creates the database record all the non-null 'columns' > are > filled. You can end up with a big list of requirements in some cases, > but > for me this eventually became a regular pattern in the UI anyway. I > provide > 'Update' actions for big fieldsets with the UI, these allow you to edit > the > set as a group of properties. There is quite a bit of coding to do > > this, > > and when you are used to HTML forms it seems silly to have to do it at > first, but it once its done its easy to test and maintain, that is the > Apache Isis payback IMO. For users this approach is kind of like a > workflow, just traverse a new object clicking all the Update buttons in > the > fieldset name panels. Tabs made this even more so. > > > A few more thoughts on the topic: > > Inline creation of referenced entities from within a create dialogue in > my > mind is a great way to streamline the usage of the any application, > because > otherwise the user would have to remember what he has to do in which > order. > For instance: before creating an entity A, he would have to know > > whether > > all the non trivial / referenced entities of that entity A are already > > in > > the database, or he would have to go and look it up. > > If A only references one other entity this approach may seem pretty > > easy, > > but let's say A references 3 or 4 or 5 other entities, then this > > becomes > > less straight forward. > > > When this is likely I have two actions, usually for collections, an > > 'Add' > > and an 'Add New' action. The Add will have a single parameter with list > of > existing entities, the Add New will collect the required property > > values > > for a valid new entity. The Add New just passes the values to an > > injected > > domain service to create the new object. > > I also suggest that the bookmarks in Isis are really useful to users, > > its > > not a big deal to skip off to another object and then come back to one > you > were recently at via the bookmarks. I think this would be something > > from > > the Naked Objects heritage of Isis, where multiple objects where > > visible. > > > I also read another post the other day asking whether the framework > supports workflows. As far as I can tell a lot (most?) of the workflows > out > there actually handle just that: offering the user the choice to select > an > existing item or to create a new one and then continue with the next > step, > thus aggregating a complex data structure little by little and most > importantly taking away from the user the burden of having to know too > much > about which data already exists in the model. > > I think offering the capability of creating entities from within the > create > dialogue in Apache Isis would already tackle a great portion of > > existing > > requirements for anything resembling a workflow at much smaller costs > than > introducing a complete new workflow system. > > > There is a workflow module part done, but interest in it doesn't seem > sufficient to finish it off (?), which is evidence in support of your > hypothesis. Workflows have their place, but to my mind using OO > programming > is not an big advantage in that place, so use something other than > > Apache > > Isis. > > > In the last days have caught myself thinking about how my design of the > domain model would affect the usability of the application, especially > since I was taking into account the order in which things would have to > be > done when the domain model gets more complex, just because of the fact > that > one has to currently make sure certain things have to exist before > > others > > (or as a matter of fast having to cancel a "create" action and go > somewhere > else and come back, which could be frustrating too). From a purely > theoretical perspective a domain model should be free from such > influences. > > What do you think? > > > The bookmarks comment is relevant. > > Read up on Evans's 'Domain Driven Design' is my strong suggestion, if > users > understand the domain design in terms of familiar class names, > relationships, action names, then you are most of the way home. > > My thinking is that there are two kinds of data, static and dynamic, > > the > > static is a pretty constant and unchanging set and you usually want to > control how new objects get created otherwise you can end up with messy > data ("I couldn't see it in the list so I created another one"). [Dan's > 'findOrCreate(String name)' approach is one simple solution, but if you > want to enforce referential integrity at the database level but not > > have > > everything appear as an object link, it gets a bit more complex I > > found, > > see derived properties] > > In contrast dynamic is something that changes frequently (new members > added > to set, property values inserted or updated, new children added). Most > domain models IMO are like this, things inside the domain that are > complex > and dynamic, things outside the domain, relatively static, beyond our > control but still of interest, and often represented inside the domain > model just by identifiers or names [In an ideal world such data would > just > be all be provided by web-services, such as envisaged in the semantic > web] > > I hope this is helpful. Just browsing the documentation from > cover-to-cover > before coding is also a good idea, there is alot to learn about, thanks > to > Dan and others. > > > Thx, > Martin > > > On Wed, Sep 28, 2016 at 6:11 PM, Dan Haywood < > [email protected] > > > wrote: > > Thanks for these ideas, Steve. > > Which in turn reminds me... we have an existing module for modelling > communication channels [1] that could be used/forked as the basis for > handling locations. (If you want all the gmap location stuff, that > > is). > > Cheers > Dan > > > [1] https://github.com/incodehq/incode-module-commchannel > > On 28 September 2016 at 11:48, Stephen Cameron < > > [email protected] > > > wrote: > > Another option to try, assuming that the Concert has been created > > already, > > is to have an action on, or contributed to, the Concert that allows > creation of a new ConcertLocation. Then the user can either set the > > concert > > location by choosing an existing location from the pick list, or by > creating an new one via the action. The location property and the > > action > > can be associated via the layout.xml or annotation means. > > I use another alternative, which is more complex, for setting activity > addresses, which is to have 'named' addresses, these are addresses used > often for different activities. So the 'Update Address' action has a > picklist of existing named addresses, or you can create a new address > > by > > filling in street1, street2, suburb. But if you give that new address a > name as well (e.g XYZ Community Hall) it becomes a new named address. > > So the Update Address action has 5 parameters, a list of existing named > addresses, a name for a new address, street1,street2, a list of > > suburbs. > > > > > On Wed, Sep 28, 2016 at 7:48 PM, Dan Haywood < > > [email protected] > > > wrote: > > Hi Martin, > > This requirement has only come up infrequently so far, not > > sufficiently > > to > > build a particular widget or programming model for it. > > Where we have required it, we've simply provided two optional > > parameters, > > one listing the existing objects, the other for the name of a new > > object. > > (This assumes that a single string is sufficient to create said new > object). > > public Concert create(@Nullable ConcertLocation > existingConcertLocation, @Nullable String newConcertLocationName, > > String > > concertName) { > > ConcertLocation concertLocation = > existingConcertLocation != null > ? existingConcertLocation > : concertLocationRepository.findOrCreate( > > newConcertLocationNam > > e); > > > return concertRepository.create(concertName, concertLocation); > } > public String validateCreate(ConcertLocation existingConcertLocation, > String newConcertLocationName, String concertName) { > if (existingConcertLocation == null && newConcertLocationName == > > null) > > return "Specify either an existing location or the name of a new > > one"; > > if (existingConcertLocation != null && newConcertLocationName != > > null) > > return "Specify either an existing location or the name of a new > > one"; > > return null; > } > > However, that has the side effect of cluttering up the common use > > case > > (new > > Concert in an existing ConcertLocation), so I don't know if it's > > worth > > the > > effort. My recommendation would simply be to treat the creation of > > concert > > locations and of new concerts independently. > > HTH > Dan > > > > > On 28 September 2016 at 09:32, Martin <[email protected]> > wrote: > > Let's say we have an entity Concert and an entity ConcertLocation > > and > > the > > model is such that a Concert would reference a ConcertLocation > > (shared > > ManyToOne association). > > In a create dialogue for the Concert entity I would like to offer > > the > > possibility to create a new ConcertLocation item if the desired > > location > > is > > not found in the dropdown or select box. > > This could for instance be by displaying a "create new location" > > icon > > next > > to the dropdown box for locations or anything else, which would > > then > > open > > another modal on top of the create dialogue to create that > new ConcertLocation. > > Once the new ConcertLocation has been created it should then appear > > in > > the > > list of available locations in the Concert create dialogue. > > How would I go about this in Apache Isis? > > I haven't found anything of the kind in the kitchen sink or the > > todo > > app > > or > > any other examples available. > > Thanks and regards, > Martin > > > > > > > > Óscar Bou Bou > Socio - IT & GRC Management Services Director > m: +34 620 267 520 > s: <http://www.govertis.com/>www.govertis.com e: [email protected] > > LinkedIn: https://www.linkedin.com/in/oscarbou > Twitter: @oscarbou <https://twitter.com/oscarbou> > > > > Este mensaje y los ficheros anexos son confidenciales. Los mismos > contienen información reservada que no puede ser difundida. Si usted ha > recibido este correo por error, tenga la amabilidad de eliminarlo de su > sistema y avisar al remitente mediante reenvío a su dirección > > electrónica; > > no deberá copiar el mensaje ni divulgar su contenido a ninguna persona. > > Su dirección de correo electrónico junto a sus datos personales constan > en un fichero titularidad de GOVERTIS ADVISORY SERVICES, S.L. cuya > finalidad es la de mantener el contacto con Ud. Si quiere saber de qué > información disponemos de Ud., modificarla, y en su caso, cancelarla, > > puede > > hacerlo enviando un escrito al efecto, acompañado de una fotocopia de > > su > > D.N.I. a la siguiente dirección: GOVERTIS ADVISORY SERVICES, S.L. Avda > Cortes Valencianas, 58 – 8º - 6ª. 46015 - Valencia, y Paseo de la > Castellana, 153, 28045 - MADRID. Asimismo, es su responsabilidad > > comprobar > > que este mensaje o sus archivos adjuntos no contengan virus > > informáticos, y > > en caso que los tuvieran eliminarlos. > > > > Óscar Bou Bou > Socio - IT & GRC Management Services Director > m: +34 620 267 520 > s: <http://www.govertis.com>www.govertis.com e: [email protected] > > LinkedIn: https://www.linkedin.com/in/oscarbou > Twitter: @oscarbou <https://twitter.com/oscarbou> > > > > Este mensaje y los ficheros anexos son confidenciales. Los mismos > contienen información reservada que no puede ser difundida. Si usted ha > recibido este correo por error, tenga la amabilidad de eliminarlo de su > sistema y avisar al remitente mediante reenvío a su dirección > > electrónica; > > no deberá copiar el mensaje ni divulgar su contenido a ninguna persona. > > Su dirección de correo electrónico junto a sus datos personales constan > en un fichero titularidad de GOVERTIS ADVISORY SERVICES, S.L. cuya > finalidad es la de mantener el contacto con Ud. Si quiere saber de qué > información disponemos de Ud., modificarla, y en su caso, cancelarla, > > puede > > hacerlo enviando un escrito al efecto, acompañado de una fotocopia de su > D.N.I. a la siguiente dirección: GOVERTIS ADVISORY SERVICES, S.L. Avda > Cortes Valencianas, 58 – 8º - 6ª. 46015 - Valencia, y Paseo de la > Castellana, 153, 28045 - MADRID. Asimismo, es su responsabilidad > > comprobar > > que este mensaje o sus archivos adjuntos no contengan virus > > informáticos, y > > en caso que los tuvieran eliminarlos. > > > > > > Óscar Bou Bou > Socio - IT & GRC Management Services Director > m: +34 620 267 520 > s: <http://www.govertis.com>www.govertis.com e: [email protected] > > LinkedIn: https://www.linkedin.com/in/oscarbou > Twitter: @oscarbou <https://twitter.com/oscarbou> > > > > Este mensaje y los ficheros anexos son confidenciales. Los mismos > contienen información reservada que no puede ser difundida. Si usted ha > recibido este correo por error, tenga la amabilidad de eliminarlo de su > sistema y avisar al remitente mediante reenvío a su dirección electrónica; > no deberá copiar el mensaje ni divulgar su contenido a ninguna persona. > > Su dirección de correo electrónico junto a sus datos personales constan en > un fichero titularidad de GOVERTIS ADVISORY SERVICES, S.L. cuya finalidad > es la de mantener el contacto con Ud. Si quiere saber de qué información > disponemos de Ud., modificarla, y en su caso, cancelarla, puede hacerlo > enviando un escrito al efecto, acompañado de una fotocopia de su D.N.I. a > la siguiente dirección: GOVERTIS ADVISORY SERVICES, S.L. Avda Cortes > Valencianas, 58 – 8º - 6ª. 46015 - Valencia, y Paseo de la Castellana, > 153, 28045 - MADRID. Asimismo, es su responsabilidad comprobar que este > mensaje o sus archivos adjuntos no contengan virus informáticos, y en caso > que los tuvieran eliminarlos. > >
