pSpaces / Programming-with-Spaces

Getting started, manuals and tutorials
46 stars 15 forks source link

Specify more clearly the classes of spaces (fifo, lifo, etc.), #5

Closed albertolluch closed 6 years ago

albertolluch commented 6 years ago
albertolluch commented 6 years ago

@michele-loreti @sequenze : me and @luhac discussed the constructors of spaces.

My understanding is that jSpace and dotSpace define an interface (Space and ISpace, respectively) which is implemented by different classes (SequentialSpace, FIFOSpace). So, creating a a space always looks like

s = new SequentialSpace();

where one uses one specific implementation of the interface.

If I remember well, @luhac would like to see a unique constructor, with the actual kind of space as a parameter, so that the above would be

s = new Space(sequential);

or just

s = new Space();

if sequential is the default.

@luhac can you remind me the rationale behind your suggestion?

@michele-loreti @sequenze : any thoughts on this?

albertolluch commented 6 years ago

@luhac @michele-loreti @sequenze : I have added a list of space implementations in

https://github.com/pSpaces/Programming-with-Spaces/blob/master/guide.md#core-space-api

From "The core API intentionally underspecifies..." until "...are optional."

Can you please check it?

@michele-loreti jSpace uses FIFO and LIFO instead Fifo, Lifo (as dotSpace and the documentation does).

@sequenze dotSpace does not provide SequentialSpace. I will add that an issue in a sec.

sequenze commented 6 years ago

s = new Space(sequential); @michele-loreti @sequenze : any thoughts on this?

If I understand @luhac correctly, he suggests that the behavior is defined as a parameter. If he suggests using a value type for this, fx. an enum, then I really dislike the idea as it goes against the principles of OOP. More specifically, each entity should be self-contained and have one single responsibility.

One way to adhere to the OOP principles and at the same time have something similar to what @luhac suggests is by implementing some simple strategies: This would and should atleast entail the following entities:

IStrategy { int GetIndex(); }

SequentialStrategy : IStrategy { public GetIndex() { ... } }

FifoStrategy : IStrategy { public GetIndex() { ... } }

and so on... Also, then the constructor would have to be invoked s = new Space(new SequentialStrategy()) etc. or in case of the default just s = new Space();

I do not see that this suggestion brings any additional clarity or coherency to the framewoek, however it bloats the instantiation of the spaces. Bad. Very bad. :D

sequenze commented 6 years ago

@sequenze dotSpace does not provide SequentialSpace. I will add that an issue in a sec.

SequentialSpace: retrieval operations return the oldest matching tuple. FifoSpace: retrieval operations return the oldest tuple, if it matches the specified template.

What is the difference? Am I missing something?

albertolluch commented 6 years ago

Let s be a SequentialSpace and f be a FifoSpace.

Execute:

s.put(0);
s.put(1);
f.put(0);
f.put(1);

Now, f.get(1) blocks because the oldest tuple in f is 0 (the head of the FIFO queue), while s.get(1) does not block.

In other words FifoSpaces are queues, while SequentialSpaces are something different.

You may argue that SequentialSpaces are weird, but that is how Promela channels (in the model checker SPIN work) and also the way tuple spaces were implemented in XKLAIM and jRESP.

albertolluch commented 6 years ago

@michele-loreti @luhac

Together with we have been discussing the names of the implementations

This is one option but shane has a different preference:

ListSpace (ex SequentialSpace) QueueSpace (ex FIFO) StackSpace (ex LIFO) PileSpace (dual of ListSpace, so like a stack but relaxed)

I think that @sequenze prefers to use Fifo, Lifo for some of them (List and Pile) but I would rather avoid it since many people associate FIFO with Queue and LIFO with Stack.

What do you think?

ghost commented 6 years ago

@sequenze

I like the idea of having an interface for a strategy, where Space() can have it as an optional parameter.

The point here is not to overcrowd the Space API with specialised constructors for a space when different behaviour strategies are needed.

I think about it this way: a lean Space API will lead to more effective use of the API. When there is a choice, a default should be provided and an optional parameter to override the default should be given too.

The best thing would be not to force a specific programming paradigm here (purely functional or purely OO), but to provide the necessary capabilities for the developer to develop as fast and cleanly with the Space API.

I think a space is created as (not specific to any particular language):

Space s = new Space();

The default strategy should be a uniform distribution. I am not much for a sequential strategy as default, as it will make the programmer lazy and not being cautious about the design: make assumptions about the order -> hard to debug design problems when API changes or a problem is solved with the API. It should be clear that unless a strategy is specified, no assumptions about order of the retrieval should be made in any way.

I see a strategy as being either:

If a space following a specific strategy is needed, one can do:

Strategy strat = new StackBasedStrategy();
Space s = new Space(strat);

Or with a custom strategy:

Strategy strat = new CustomDistributionStrategy();
Space s = new Space(strat);

Also, there will not be a need to maintain a series (or add more) specialised space constructors with this way of doing it.

sequenze commented 6 years ago

> I like the idea of having an interface for a strategy, where Space() can have it as an optional parameter. The point here is not to overcrowd the Space API with specialised constructors for a space when different behaviour strategies are needed.

If you suggest is that: ISpace space = new Space(new FifoStrategy()) // ISpace, Space, FifoStrategy

is syntactically and/or semantically superior to

ISpace space = new FifoSpace(); // ISpace, FifoSpace, SpaceBase

then i disagree. Both representations have the same number of entities, thus the programmer needs to be aware of an equal amount of entities to fully utilize the supported features. Also, the notion of using a strategy pattern actually increases the complexity slightly, as the behavior is injected opposed to being supported by the concrete type. Finally, inheritance is not something the students should be strangers to. If that's a hard concept for them to grasp, then its probably a good thing they are being introduced to it yet again.

"The best thing would be not to force a specific programming paradigm here (purely functional or purely OO" <----- I completely disagree.

OOP and FP are different paradigms. They approach the same problems differently. Sure, you can develop programs without having side effects in OOP languages. Likewise, you can develop programs using nothing but states in FP languages. But why would you? Metaphorically speaking, its the equivalent of using a hammer with screws. Its all about the effort...

> but to provide the necessary capabilities for the developer to develop as fast and cleanly with the Space API. I agree. Fast and clean code should be the goal for any programmer. But I disagree with you on how to achieve it.

> I think about it this way: a lean Space API will lead to more effective use of the API. Sure. But effective use of a smaller API isn't the same as an more effective API. Also, I don't agree that the strategy pattern leads to a more lean API.

> When there is a choice, a default should be provided and an optional parameter to override the default should be given too. In my opinion: When there is options, then defaults are generally bad. For the expert who knows the API it wont make a difference, but the novice will overlook the fact that it has a hidden setting.

> Or with a custom strategy: Or inherit the base class or implement the interface.

> Also, there will not be a need to maintain a series or add more specialized space constructors with this way of doing it. I'm not entirely sure what you mean here. For every strategy you want, you need to implement one entity. Currently dotSpace implements 3 concrete Space derivatives. Each of them implements the strategy directly. Nothing more.

The default strategy should be a uniform distribution. I am not much for a sequential strategy as default, as it will make the programmer lazy and not being cautious about the design: make assumptions about the order -> hard to debug design problems when API changes or a problem is solved with the API.

Honestly, I haven't utilized nor considered using a data structure where the lookup order was random before. I truly have a hard time accepting that a uniform distribution is more useful and applicable in the general case than that of any form of sequential lookup. Also, the problem you state (assumptions about the order) only exist because you insist on a default behavior. Having concrete entities, each maintaining a distinct behavior, completely negates the problems you mention.

hard to debug design problems when API changes... Which is exactly why 'default parameters' are bad.

Again, this is just my opinion.

albertolluch commented 6 years ago

@michele-loreti and me have agreed on the names

SequentialSpace
QueueSpace 
StackSpace
PileSpace 

The specification has been updated accordingly.

albertolluch commented 6 years ago

Note that these are types of spaces but we do not impose a specific realisation of them. Currently, they are implemented as classes in JSpaces and dotSpaces, but they could be implemented in any other way (say with the above suggested strategies). I will update the documentation to be more clear in what are the concepts that are required to be provided, and which are just suggestions of possible conventions.

albertolluch commented 6 years ago

Anyhow, since there is agreement on the classes, I am closing this issue.