Win a copy of TensorFlow 2.0 in Action this week in the Artificial Intelligence and Machine Learning forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Paul Clapham
  • Bear Bibeault
  • Jeanne Boyarsky
Sheriffs:
  • Ron McLeod
  • Tim Cooke
  • Devaka Cooray
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Jj Roberts
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • salvin francis
  • Scott Selikoff
  • fred rosenberger

How to link the methods of a few classes into one object?

 
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Current Situation:
--------------------

I've written a client to work with a network resource. The client has:
- Basic session management (connect, disconnect, read, write)
- DSL (login, do this, do that)
- Special data types to be doing all sorts of operations on the data to be dispatched and the data that results from the DSL

For example, some automation scripts might include the following code:


The users really like this client. Finally, non-expert users can automate a very technical client using DSL they know and no highfalutin Java stuff!
There are already 34 automation scripts (that's 34 times more automation than my team has ever had, after 3 years and a hundred thousand pounds spent on trying!).

Problem:
----------

Currently, all the data types, DSL, response checks and much more are all in OldStyleClient class!
A. It looks messy and unprofessional
B. I want to add more layers (for example, I want to take out the session management as a separate object, so I can do more stuff that's unrelated to the session)

Ideally, I want to break OldStyleClient into
ClientSession - main class that links everything. Has the basic Session Management methods and the datatypes
ClientDSL - a class containing methods that operate on the ClientSession
ClientChecks - all sorts of checks like the aforementioned checkRC(600), or checkCreatedContactIsValid(), etc...
and much more...

I know I can use 'extend' (and I am using it to great success, because this client is a member of a family of related clients)
But I don't know how I can bring methods from different classes to be used on the same object?
I want to keep that beautiful code style of:
currentSession.someSessionManagement
currentSession.someDSL
...

I have heard about interfaces but I haven't used them at all and I am not sure they are what I need. I was told I could use "composition instead of inheritance" but not sure how?
Also, it seems that the interfaces functionality is mainly to enforce a contract and multiple inheritance is merely a side effect.

Any ideas?

PS: Please let's not turn this into a "you can tuck checkRC into the preceding methods" - there's a reason we need this granularity and it's just... MUAH! as it is

Many thanks in advance!
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One idea that I have but not sure where to start is if I could do something like this:
ClientSession - my main class with some overhead data types and methods
ClientDSL - the class would be ClientDSL but the object type would be a ClientSession object!
ClientChecks - the class would be a ClientChecks but the object type would be a ClientSession object!

Then, I could do something like:


Because currentSession is the same object type as all 3 methods, I imagine I could invoke instance methods from all classes on the same object.

Not sure how to compose/inherit this...
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK I have an idea that I'd like to run past you, please:

Since the original post, I've looked into interfaces, default methods, composition with delegation, etc... I've seen that all of these solutions require some form of "registration" of extended methods.
Meaning: if I add a new DSL method, I'll have to either update an interface or a "delegation" method as well (for each new DSL method).

Instead, I've been playing with creating new, different objects and linking them using just a "gateway" method, like so:


And then the classes containing the extended methods would look like so:


And now, I am able to do:


My main concern here is that I am creating an object just to so I can link the main object to the class containing the extended methods.
Would you consider this superfluous object "ugly" or would it be a performance problem?
 
Marshal
Posts: 25969
70
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So far you're mostly talking about programming, but what you describe is (I think) a design pattern called Facade. Follow that link to the Wikipedia article and maybe it will clarify your thoughts a bit. There's a Java example there too.
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was just looking at the facade pattern yesterday.
From what I've been able to gather, it's more about hiding methods and grouping the units of a system.

I am more looking for: being able to use a rich set of methods without all methods defined in the same class, or without skipping between objects in the automation script
 
Paul Clapham
Marshal
Posts: 25969
70
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As you said in your original post:

But I don't know how I can bring methods from different classes to be used on the same object?



So it looks like you want to have a single object behind which there are different classes doing the same work. Also in your original post was "OldStyleClient" which appeared to be the same sort of thing. That's a facade in my opinion.

Or as you just said:

being able to use a rich set of methods without all methods defined in the same class, or without skipping between objects in the automation script



You want only one object, but you want to use methods from different classes. The "one object" is a facade, behind which are those different classes. I don't see why a facade shouldn't support a "rich" set of methods; it's true that examples of the Facade pattern aren't like that, but then they are just examples.
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Interesting. I certainly thought that example was exhausting of the main facade pattern idea.
I gave it another go during the weekend and I was unable to link my classes that way.

Could I ask for an example, please?


PS:
Adding a layer, like I've done with my method chaining, has some advantages.
Now, when the user tries to code .myDslMethod() into the script, they only see SessionDsl methods suggested by the IDE, like so:
Old Style:
currentSession. <- IDE spews all applicable methods, which is a little spammy

New Style:
currentSession.dsl(). <- IDE suggests only DSL methods - a nice time saving and reduction of error chance

I just don't like creating a new object just so I can link methods from its class into my "single point of service" class.
So, I would still like to see if I can get that facade to work and if it has more advantages than my current method chaining
 
Paul Clapham
Marshal
Posts: 25969
70
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Todor Kolev wrote:
Now, when the user tries to code .myDslMethod() into the script, they only see SessionDsl methods suggested by the IDE, like so:
Old Style:
currentSession. <- IDE spews all applicable methods, which is a little spammy

New Style:
currentSession.dsl(). <- IDE suggests only DSL methods - a nice time saving and reduction of error chance

I just don't like creating a new object just so I can link methods from its class into my "single point of service" class.



I don't see too much of a problem with that. Your facade is large enough that it has several distinct categories of actions behind it, so you'd like a way of grouping the actions in each category for the user's convenience.

You could do that by giving all of the DSL methods names which start with "dsl", so that the IDE would just suggest those methods after the user typed "dsl", for example. So you might have dslDoThis("hello"), for example.

Or your idea of an object to take care of the DSL objects isn't that bad, but I'd suggest two things: (1) that object should be provided from behind the facade and not created by the user, and (2) its only purpose would be to hand off method calls to the real workers behind the facade. So it's a "sub-facade" if you want a name for it.

Performance problem? No. Calling a method doesn't even take a microsecond these days.
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Turns out the sub-facade idea has a limitation I again struggle to cope with, without devolving my pattern.
I want the result from the method in the secondary class to be returned to the primary class's method.
However, when chaining the secondary method, the return goes to the total expression (the method that called the method in the primary class) and not to my primary class.
Illustration:

client(); is a method in MySession which returns the client object
connect(); is a method in MyClient, which returns some response data that needs to be verified to ensure a good connection (and I want to hide that from the automation users)

currentSession.client().connect();

The above expression causes the return from connect to go into the automation script, which is not ideal, as the automation users have no idea what to do with that

Previously, I had connect(); inside MySession and in that way currentSession.connect(); would validate the response - all in one line.

So, coming back to the facade pattern - I am really ashamed to admit defeat here!
Any chance to see a piece of code that would show me how to basically implement the idea from the topic of the post?
Please

Happy to make a $10 donation to a charity of your choice, as a no-warranty-implied reward for giving a stupid man some direction!
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think an update could be interesting to someone who has run into the same problem.

The bad news are that I haven't been able to find a java coding functionality or pattern that solves this thing in a "mix and match" style.
What I was able to do is have a thought about what I am going for with what tools I have and combine them in a way that works for me, specifically.

Lucky that my stuff falls into a hierarchical model:
* A Session is only valid if the Checks are passing
* User can only run a Check after doing something. They do something via the DSL
* DSL can only do things if it has a Client

So:


Now, I can call methods from all the classes on the MySession object.
The limitation of this is that it has a direction: You can't call a DSL method from the client.
Luckily, again, I don't need to, as DSL is an enrichment of the client.

There remained two problems I had to solve:
1. The session object contained quite a lot of data on how to connect the client
2. All classes need to handle a "response" field

So:



And:



* Now, classes all the way down to MySession will have a reference to the MySession object.
It is a little funny that MySession has a field that refers itself but it's just one little ugly thing that enables a lot of pretty things. So, I am willing to live with that.
Once MySession is done constructing, the client can connect without passing fields like crazy, it can just refer to it's parentSession and get the fields from there.
In any class, if I need information, I don't need to write monster, 7-field methods, just dig into the parentSession reference.

I haven't gone there yet, but I know I will need sessions that are spun off a "parent" session and I think this above trick will actually play right into this.
 
Marshal
Posts: 70726
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Todor Kolev wrote:. . .. . .

Please explain that part; there is something iffy about that. Are you allowing a this reference to escape a constructor?
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I need MyClient to know the SSL/Plaintext connection parameters (6 or 3 fields, and another Boolean field about whether an SSL/Plaintext socket is needed).
I could have implemented the client with all methods being static but I wanted to shorten method signatures. A session has only one client, anyway...

Also, MyDsl needs some more data (4 fields like user name, pass, client-transaction-identifier...) (in most cases, one will use default user/pass but, also, a
way to log in with custom user/pass is needed) and I would like NOT to pass those everytime a DSL is called.
So, I hooked them up on the session object. I didn't even want to pass that one. So, I made MySession as an extension of MyDsl (via MyChecks, extending
MyDsl), which is an extension of the MyClient.

As for calling this inside a constructor. I am not sure what is the problem? If there's a design principle I am infringing on here, I am not aware of it (but
can learn about it if I am shown).
I do recall having some problems with constructor chaining (when trying to use 'this' there) when the classes being extended had explicit constructors (not anymore).
I later deemed those constructors redundant anyway and went with the "uncoded" constructor (lots of different opinions on the web about how to call
the constructor created by the compiler when the class doesn't explicitly define a constructor with written code).

To be honest, I may be under the level necessary to answer your question!
Not even sure what "escaping a constructor" means in this context...
I am happy to answer something more specific or test something and tell you how it works, if you would like.
 
Campbell Ritchie
Marshal
Posts: 70726
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ohter code will have a reference to your object. What happens if you allow a this reference to escape the constructor is that other code can use the current object immediately. This is a particular problem in a multi‑threaded environment because the object may not necessarily be in a consistent state. I saw this sort of thing once on the Ranch:-Even though the use of this appears in the last line of the constructor, there is no guarantee that the lines will be executed or completed in the order 3‑4‑5‑6. It is therefore possible for the school to obtain and use the Pupil object when the information has only been partially initialised, passing errors into other code. More information in this old threa‍d.
I don't know enough about your code to know whether you are allowing a this reference to escape. Maybe something else is happening. Maybe that assignment has no effect. I don't know. Seeing the use of this in a constructor made me suspicious.

Todor Kolev wrote:. . . I later deemed those constructors redundant anyway and went with the "uncoded" constructor (lots of different opinions on the web about how to call the constructor created by the compiler when the class doesn't explicitly define a constructor with written code). . . .

That is called a default constructor. All other opinions are wrong
I worry when I see classes without proper constructors. There is no guarantee that they will ever have all their fields correctly initialised, so the objects may be in an inconsistent state when they are used. A similar potential source of errors.
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am trying to understand how these lines could execute out of order.

1. Is it only a problem for multi-threaded design?
I am not using multi-threading right now (but I might want to, in the far future)

2. What are the threads doing that can lead to this failure?

a) Are they "sharing" code lines, like:
Thread A: creates blank object, assigns fields Name and DoB
Thread B: assigns gender
Thread C: calls registerPupil


b) Or, is it a problem at the higher level, like:
Thread A: creates and starts to initialize fields
Thread B: school.getMaleFemaleRatio(); (reads all registered pupils, calculates a gender distribution = will produce a bad result, because the pupil in Thread A has a default Gender, not a correct gender)

I am hoping #1 is yes!
I am hoping #2 b!
Or else: this sounds like a total mess! How could one code ANYTHING when threads pick up random code?
 
Campbell Ritchie
Marshal
Posts: 70726
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Todor Kolev wrote:I am trying to understand how these lines could execute out of order.

The runtime can optimise execution in all sorts of ways, which can cause lines whose population of variables are disjoint to be taken in any order. If they apply to different variables, it must be all right to take the lines in a different order. The JVM might even run several thre‍ads itself, and distribute execution of your constructor between those threa‍ds.

1. Is it only a problem for multi-threaded design? . . .

No.

2. What are the threads doing that can lead to this failure?

a) Are they "sharing" code lines, like:
Thread A: creates blank object, assigns fields Name and DoB
Thread B: assigns gender
Thread C: calls registerPupil


b) Or, is it a problem at the higher level, like:
Thread A: creates and starts to initialize fields
Thread B: school.getMaleFemaleRatio(); . . .

Don't know. Could be any of those. Could be different from what happened yesterday.

How could one code ANYTHING when threads pick up random code?

Threads don't pick up random code. The JVM must maintain correctness of all variables. If the gender variable is only used in line 5, then it can't be wrong to execute line 5 before line 4. Each thre‍ad will execute code using the gender variable so as to get the correct result.
 
Campbell Ritchie
Marshal
Posts: 70726
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What is your assignment = this actually doing? We can probably work that out with some more details.
 
Todor Kolev
Ranch Hand
Posts: 72
1
Python Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is shocking news to me! I thought java code line execution order is "guaranteed"!

'this', in my constructor assigns the field of the current instance a reference to the instance.
My constructor just receives an object and assigns fields, extracting from the input object:



Again, the reason I am doing this (no pun intended) is because classes which MySession extends (MyChecks, which extends MyDsl, etc...) need to
all work on the same object, without all 40 methods defined in the same class.

Example:




I think in my particular case, so far, I am safe:
1. Any incomplete data will result in a failed connection, containing the explosion pretty soon
2. None of this is actually running in production. It's a test suite
3. I wrote a lot of defensive code - not because I understand Java's memory model and automatic multi-threaded optimization, but because I don't trust myself to have passed the data correctly in the first place
Any field I created and later rely upon will be tested and RunTimeComputerSaysNO will be raised, cutting off further work
 
Campbell Ritchie
Marshal
Posts: 70726
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Todor Kolev wrote:. . . 'this', in my constructor assigns the field of the current instance a reference to the instance. . . .

That looks like a recursive definition to me. At least you can pretty well rely on suffering an exception if you get problems with that recursion.

A “guarantee” about order of execution of lines is not worth very much. What you get is a guarantee about the semantics of execution:-There is no need to worry about line 3 being executed before line 4, nor about lines 3 and 5 being optimised away to i += 2; But you can be sure that line 6 will print 125. The possible versions of the program are equivalent to one another, and there is no difference between the two programs. Lines 2 and 4 are independent of the other four lines.
 
The only thing that kept the leeches off of me was this tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic