Jump to content

Talk:Fluent interface: Difference between revisions

Page contents not supported in other languages.
From Wikipedia, the free encyclopedia
Content deleted Content added
m Fixed up with a title
Fix high-priority Linter errors.
 
(40 intermediate revisions by 23 users not shown)
Line 1: Line 1:
{{WikiProject Computer science|class=Stub|importance=}}
{{WikiProject banner shell|class=Stub|
{{WikiProject Computer science|importance=}}
}}


== Returning this In Chained Methods ==
Under "Implementation":
"... by having each method return the object to which it is attached, often referred to as this or self"
Where did this criterion come from? It didn't appear in, for example, Fowler's original article, which instead explicitly said
"You should choose your return type based on what you need to continue fluent action.", going on to use JMock as an example of a fluent library where the chained methods often return objects with different types from that which the methods were called on: those different types being more useful than simply finishing with "return this;" would have been. <!-- Template:Unsigned IP --><small class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/125.237.145.229|125.237.145.229]] ([[User talk:125.237.145.229#top|talk]]) 02:23, 4 August 2024 (UTC)</small> <!--Autosigned by SineBot-->

== Method Chaining vs Fluent Interface ==

According to the definition of fluent interface, this is not a fluent interface

<syntaxhighlight lang="javascript">
const result = somestring.trim().padStart(10).replace('abc', 'def').padEnd(10);
</syntaxhighlight>

A Fluent Interface chains on "this" which each method modifying the same object. The code above a new object is returned from each method, them a method of that new object is called. That is just method chaining.

To spread it out, to be a fluent interface the follow test has to pass

<syntaxhighlight lang="javascript">
const a = somestring.trim();
const b = a.padStart(10);
const c = b.replace('abc', 'def');
const d = c.padEnd(10);
const isFluentInterface = (a === b && a === c && a === d); // isFluentInterface will be false here
</syntaxhighlight>

An example that is a fluent interface

<syntaxhighlight lang="javascript">
class Calc {
constructor(v) { this.v = v; }
add(v) { this.v += v; return this; }
subtract(v) { this.v -= v; return this; }
multiply(v) { this.v *= v; return this; }
divide(v) { this.v ;= v; return this; }
};

const result = (new Calc(1)).add(3).subtract(2).multiply(4).divide(3);
</syntaxhighlight>

Applying the test above it passes

<syntaxhighlight lang="javascript">
const a = new Calc(1);
const b = a.add(3);
const c = b.subtract(2);
const d = c.multiply(4);
const e = d.divide(3);
const isFluentInterface = (a === b && a === c && a === d && a === e); // isFluentInterface will be true here
</syntaxhighlight>

== Problem with the C# sample code ==
Hello!
Hello!


1) I tried the c#-Sample, but the compiler alerted 12 Syntax-Errors. Please give a sample with runnable code.
1) I tried the C# sample code, but the compiler alerted 12 syntax errors. Please give a sample with runnable code.


2) The "fluent-interface-benefit" (short intuitive code) is not demonstrated very convincing. I would prefer to see something like:
2) The "fluent-interface-benefit" (short intuitive code) is not demonstrated very convincing. I would prefer to see something like:


<source lang="csharp">
<syntaxhighlight lang="csharp">
IConfiguration config = ConfigurationFluent.Create().Color("blue").Height(1).Length(2).Depth(3);
IConfiguration config = ConfigurationFluent.Create().Color("blue").Height(1).Length(2).Depth(3);
</syntaxhighlight>
</source>
or
or
<source lang="csharp">
<syntaxhighlight lang="csharp">
IConfiguration config = ConfigurationFluent.CreateColored("blue").Height(1).Length(2).Depth(3);
IConfiguration config = ConfigurationFluent.CreateColored("blue").Height(1).Length(2).Depth(3);
</syntaxhighlight>
</source>


(Create() or CreateColored() would be static methods, returning a new instance as an "entry-Point" into the fluent interface.
(Create() or CreateColored() would be static methods, returning a new instance as an "entry-Point" into the fluent interface.


That is no really good Sample too, because c#2008 provides the with-Keyword, so one could instantiate without fluent interface as well:
That is no really good Sample too, because C# 2008 provides the with-Keyword, so one could instantiate without fluent interface as well:


<source lang="csharp">
<syntaxhighlight lang="csharp">
var config = new Configuration() with { Color = "blue", Height = 1, Length = 2, Depth = 3 };
var config = new Configuration() with { Color = "blue", Height = 1, Length = 2, Depth = 3 };
</syntaxhighlight>
</source>


3) A better sample would result in stuff like:
3) A better sample would result in stuff like:


<source lang="csharp">
<syntaxhighlight lang="csharp">
// List<SpecialItem> _SpecialItems = new List<SpecialItem>();
// List<SpecialItem> _SpecialItems = new List<SpecialItem>();
SpecialItem.CreateColored("blue").Height(1).Length(2).Depth(3).AddTo(_SpecialItems);
SpecialItem.CreateColored("blue").Height(1).Length(2).Depth(3).AddTo(_SpecialItems);
</syntaxhighlight>
</source>


That would demonstrate, how fluent interface reduce nesting. Compare to:
That would demonstrate, how fluent interface reduce nesting. Compare to:


<source lang="csharp">
<syntaxhighlight lang="csharp">
// List<SpecialItem> _SpecialItems = new List<SpecialItem>();
// List<SpecialItem> _SpecialItems = new List<SpecialItem>();
_SpecialItems.Add(new SpecialItem() with { Color = "blue", Height = 1, Length = 2, Depth = 3 });
_SpecialItems.Add(new SpecialItem() with { Color = "blue", Height = 1, Length = 2, Depth = 3 });
</syntaxhighlight>
</source>
Unfortunately the benefit "help from Intellisense" (a fluent interface supports fluent writing code) cannot be shown in an article, or would you like to add screenshots?
Unfortunately the benefit "help from Intellisense" (a fluent interface supports fluent writing code) cannot be shown in an article, or would you like to add screenshots?


Line 42: Line 96:
----
----


IMO the published sample is garbage. Chaining in itself does not make for readability and the ALT.NET community is severely abusing mere chaining with this misunderstanding. There's nothing less readable about <source lang="csharp">myObject.SetValueX(1);
IMO the published sample is garbage. Chaining in itself does not make for readability and the ALT.NET community is severely abusing mere chaining with this misunderstanding. There's nothing less readable about <syntaxhighlight lang="csharp">myObject.SetValueX(1);
myObject.SetValueY(2);</source> than <source lang="csharp">myObject.SetValueX(1).SetValueY(2);</source> In my opinion, this actually makes it less readable because these are distinct statements that are being slurred together.
myObject.SetValueY(2);</syntaxhighlight> than <syntaxhighlight lang="csharp">myObject.SetValueX(1).SetValueY(2);</syntaxhighlight> In my opinion, this actually makes it less readable because these are distinct statements that are being slurred together.


I agree that the samples from [[User:ErfinderDesRades|ErfinderDesRades]] are better.
I agree that the samples from [[User:ErfinderDesRades|ErfinderDesRades]] are better.
Line 52: Line 106:
In the PHP sample, what is this part good for?
In the PHP sample, what is this part good for?


<source lang="php">
<syntaxhighlight lang="php">
<?php
<?php
session_start();
session_start();
Line 59: Line 113:
require_once 'config.php';
require_once 'config.php';
?>
?>
</syntaxhighlight>
</source>


== Monad ==
== Monad ==
Line 68: Line 122:


The article correctly states that ''a fluent interface entails more than just method chaining'' but then goes on to to show examples that solely use Method Chaining. This is misleading. The article and the examples could be improved to reflect a Fluent Interface' role in creating internal DSLs. This would make the distinction more clear. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/87.123.52.156|87.123.52.156]] ([[User talk:87.123.52.156|talk]]) 08:46, 22 September 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->
The article correctly states that ''a fluent interface entails more than just method chaining'' but then goes on to to show examples that solely use Method Chaining. This is misleading. The article and the examples could be improved to reflect a Fluent Interface' role in creating internal DSLs. This would make the distinction more clear. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/87.123.52.156|87.123.52.156]] ([[User talk:87.123.52.156|talk]]) 08:46, 22 September 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->

: Same comment from my side. The C++ example in fact ''does'' implement a fluent interface, but not so the other examples. One correct example is much more worth than a dozen of examples whereof only one really illustrates the point. Since nothing happened since this comment from 2010 I am going to remove the other examples. --[[User:Chiccodoro|Chiccodoro]] ([[User talk:Chiccodoro|talk]]) 11:15, 7 September 2012 (UTC)
::The C++ example is also unnecessarily verbose. What about just deleting them all and adding a concise example in pseudo-code? As soon as you use a real language, people start getting all fanboyish and feel compelled to add their favorite one to the mix. <small class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/82.9.176.129|82.9.176.129]] ([[User talk:82.9.176.129|talk]]) 03:15, 18 December 2014 (UTC)</small><!-- Template:Unsigned IP --> <!--Autosigned by SineBot-->


== JQuery ==
== JQuery ==
Line 74: Line 131:


Also, I'd like to echo the above topic's concern. This article doesn't make clear what the requirements for fluent interfaces are, beyond method chaining. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/208.91.1.14|208.91.1.14]] ([[User talk:208.91.1.14|talk]]) 22:11, 27 October 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->
Also, I'd like to echo the above topic's concern. This article doesn't make clear what the requirements for fluent interfaces are, beyond method chaining. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/208.91.1.14|208.91.1.14]] ([[User talk:208.91.1.14|talk]]) 22:11, 27 October 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->


jQuery (note capitalization) definitely at least uses method chaining<ref>http://learn.jquery.com/using-jquery-core/working-with-selections/</ref>. When you start with a selection of elements — e.g., $("li") to select all list items in the page — then most chained functions do indeed return the same collection (or perhaps a reduced/expanded collection) for further operations. Honestly, the Martin Fowler piece cited in the main article isn't terribly clear on what would be required to call something a "Fluent interface" either, though it does cite JMock as an example.
[[User:Davidhbrown|Dave Brown]] ([[User talk:Davidhbrown|talk]]) 01:11, 8 April 2013 (UTC)

{{reflist-talk}}


==The non-existence of C# 3.5==
==The non-existence of C# 3.5==
Line 80: Line 143:


I don't think C# 3.5 exist; there is C# 3.0 and .NET Framework 3.5. Do you agree? --[[User:Mortense|Mortense]] ([[User talk:Mortense|talk]]) 03:09, 17 November 2010 (UTC)
I don't think C# 3.5 exist; there is C# 3.0 and .NET Framework 3.5. Do you agree? --[[User:Mortense|Mortense]] ([[User talk:Mortense|talk]]) 03:09, 17 November 2010 (UTC)

==Single-statement nature and debugging==

Issues raised in this comment were addressed, please see the 'Problems' section.

{{strikediv|1=
The article should elaborate on the problematic side of fluent style, which is debugging: fluent chains constitute a single statement or expression, which can be problematic when debugging, compared to more classic styles.

Typically, for many languages you are not able set breakpoints within a chain, and stepping will often be problematic.

There is also an issue with crash stack reports, in which a fluent chain will be treated as a single statement when the debug information is limited to statements (which for many languages is the case). That can make identifying which method call triggered an issue ambiguous if the same method is present more than once in a chain. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/88.174.31.159|88.174.31.159]] ([[User talk:88.174.31.159|talk]]) 20:58, 7 January 2011 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->
}}

== Problems > Subclasses ==

In Java, [[Generics_in_Java|Generics]] are used to enable subclassing without the subclasses having to implement all parent methods just to change the return type. [http://code.google.com/p/jatl/ JATL] is a good example how it is done. <span style="font-size: smaller;" class="autosigned">— Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/94.143.89.37|94.143.89.37]] ([[User talk:94.143.89.37|talk]]) 19:17, 25 December 2012 (UTC)</span><!-- Template:Unsigned IP --> <!--Autosigned by SineBot-->

== Minor Problem with the Java sample code ==
With the font being used and the use of the variable name "l", it requires some thought to see that "l" is not "1" in pack( l ).

I tried changing "l" to "label" but that made the alignment of the grid method invocations look ... a bit ... ugly.

So I thought I'd just mention my problem with the "l" here. <span style="font-size: smaller;" class="autosigned">— Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/219.88.170.8|219.88.170.8]] ([[User talk:219.88.170.8|talk]]) 19:44, 20 January 2014 (UTC)</span><!-- Template:Unsigned IP --> <!--Autosigned by SineBot-->


The sample has a WRONG reference to Packer200, which is used for handling JAR.
Its original reference was https://java.net/projects/packer but the java.net site closed. <!-- Template:Unsigned IP --><small class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/2001:F70:8C40:500:858F:B19C:A296:5FEE|2001:F70:8C40:500:858F:B19C:A296:5FEE]] ([[User talk:2001:F70:8C40:500:858F:B19C:A296:5FEE#top|talk]]) 14:02, 28 October 2021 (UTC)</small> <!--Autosigned by SineBot-->

== Monad? ==

Isn't this kind of style similar to a Monad? Should http://en.wikipedia.org/wiki/Monad_(functional_programming) be linked in the text? <small><span class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[User:Sukima|Sukima]] ([[User talk:Sukima|talk]] • [[Special:Contributions/Sukima|contribs]]) 22:29, 21 May 2014 (UTC)</span></small><!-- Template:Unsigned --> <!--Autosigned by SineBot-->

Re monads - this is a Javascript and purescript comparison showing this is just monads. https://github.com/pelotom/purescript-d3#example
Here is the commentary: https://twitter.com/pelotom/status/483504492034269184 <span style="font-size: smaller;" class="autosigned">— Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/124.170.192.192|124.170.192.192]] ([[User talk:124.170.192.192|talk]]) 04:36, 19 July 2014 (UTC)</span><!-- Template:Unsigned IP --> <!--Autosigned by SineBot-->

== Example Farm ==

This is yet another computer science article that has turned into a large body of inconsistent and completely unecessary examples. The JavaScript section is (as usual) particularly egregious. A single pseudo-code example would more than suffice. <small class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/82.9.176.129|82.9.176.129]] ([[User talk:82.9.176.129|talk]]) 03:11, 18 December 2014 (UTC)</small><!-- Template:Unsigned IP --> <!--Autosigned by SineBot-->

== Not a Monad ==

Bind is not the equivalent of a map operation, which is what is needed for method chaining. This is a misunderstanding of monads, and should be removed. <small class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/98.189.26.19|98.189.26.19]] ([[User talk:98.189.26.19|talk]]) 22:26, 12 February 2015 (UTC)</small><!-- Template:Unsigned IP --> <!--Autosigned by SineBot-->

== return this; vs. copy-on-write ==

I think this article should mention the difference between two semantic variants of the fluent interface pattern that I've encountered: one where all mutators end with <code>return this;</code> and one ([[copy-on-write]]) where the implementing classes are immutable and the mutators return a modified copy. [[User:NeonMerlin|<span style="background:#000;color:red;border:#0f0 solid;border-width:1px 0">Neon</span>]][[User talk:NeonMerlin|<span style="background:#0f0;color:#000;border:red solid;border-width:1px 0">Merlin</span>]] 02:22, 1 July 2018 (UTC)

== Java recursive generics ==

The Java section has only usage examples from language libraries and doesn't show how you can build fluent interfaces yourself with recursive generics and other techniques. --[[User:Iamrcr|Iamrcr]] ([[User talk:Iamrcr|talk]]) 23:49, 20 February 2019 (UTC)

== Java 8 ==

Should we list Java 8 Streams under the main fluent section as this is now builtin to the language? <!-- Template:Unsigned --><small class="autosigned">—&nbsp;Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[User:Ginister|Ginister]] ([[User talk:Ginister#top|talk]] • [[Special:Contributions/Ginister|contribs]]) 11:03, 27 March 2019 (UTC)</small> <!--Autosigned by SineBot-->

== D programming language and UFCS ==

In [[D language]], there is this transparent feature called UFCS (Uniform Function Call Syntax), which for any call <code>x.f(y, z)</code>, if the method f is not in the object / variable x, is translated to <code>f(x, y, z)</code> and the function f and its overloads are searched in all imported modules and symbols in the current scope. This allows fancy extensions, and Fluent like operations that can be extended by the user:

<syntaxhighlight lang="D">
import std.stdio : writeln;
import std.algorithm.iteration : filter;
import std.range : iota;

void main()
10.iota // returns numbers from 0 to 9
// filter for even numbers
.filter!(a => a % 2 == 0)
.writeln(); // writes them to stdout

// Traditional style:
writeln(filter!(a => a % 2 == 0)
(iota(10)));
}
</syntaxhighlight>

The two statements are exactly equivalent, and UFCS is basically a syntax sugar. However, it does allow extending any type, and adding fluent style operations.

<syntaxhighlight lang="D">
class A {
public:
int a, b, c;
auto setA(int a_) { a = a_; return this; }
}

auto setB(A t, int b_) { t.b = b_; return t; }

auto obj = A().setA(5).setB(8);
</syntaxhighlight>

will work (as long as setB has access to the field b). setB doesn't even need to be in the same module. In fact due to powerful metaprogramming (mixins and mixin templates) and compile time introspection (compile traits), it is possible to automate generation of fluent interfaces for any class. Just my two cents. One my argue that this is just a syntax sugar, but so is 'Fluent' interface. It is just to save creating temporary variables with names, and making code readable from left to right, which UFCS enables. [[Special:Contributions/81.6.34.172|81.6.34.172]] ([[User talk:81.6.34.172|talk]]) 21:07, 29 April 2020 (UTC)

Latest revision as of 14:03, 20 October 2024

Returning this In Chained Methods

[edit]

Under "Implementation": "... by having each method return the object to which it is attached, often referred to as this or self" Where did this criterion come from? It didn't appear in, for example, Fowler's original article, which instead explicitly said "You should choose your return type based on what you need to continue fluent action.", going on to use JMock as an example of a fluent library where the chained methods often return objects with different types from that which the methods were called on: those different types being more useful than simply finishing with "return this;" would have been. — Preceding unsigned comment added by 125.237.145.229 (talk) 02:23, 4 August 2024 (UTC)[reply]

Method Chaining vs Fluent Interface

[edit]

According to the definition of fluent interface, this is not a fluent interface

const result = somestring.trim().padStart(10).replace('abc', 'def').padEnd(10);

A Fluent Interface chains on "this" which each method modifying the same object. The code above a new object is returned from each method, them a method of that new object is called. That is just method chaining.

To spread it out, to be a fluent interface the follow test has to pass

const a = somestring.trim();
const b = a.padStart(10);
const c = b.replace('abc', 'def');
const d = c.padEnd(10);
const isFluentInterface = (a === b && a === c && a === d);  // isFluentInterface will be false here

An example that is a fluent interface

class Calc {
  constructor(v) { this.v = v; }
  add(v) { this.v += v; return this; }
  subtract(v) { this.v -= v; return this; }
  multiply(v) { this.v *= v; return this; }
  divide(v) { this.v ;= v; return this; }
};

const result = (new Calc(1)).add(3).subtract(2).multiply(4).divide(3);

Applying the test above it passes

const a = new Calc(1);
const b = a.add(3);
const c = b.subtract(2);
const d = c.multiply(4);
const e = d.divide(3);
const isFluentInterface = (a === b && a === c && a === d && a === e);  // isFluentInterface will be true here

Problem with the C# sample code

[edit]

Hello!

1) I tried the C# sample code, but the compiler alerted 12 syntax errors. Please give a sample with runnable code.

2) The "fluent-interface-benefit" (short intuitive code) is not demonstrated very convincing. I would prefer to see something like:

IConfiguration config = ConfigurationFluent.Create().Color("blue").Height(1).Length(2).Depth(3);

or

IConfiguration config = ConfigurationFluent.CreateColored("blue").Height(1).Length(2).Depth(3);

(Create() or CreateColored() would be static methods, returning a new instance as an "entry-Point" into the fluent interface.

That is no really good Sample too, because C# 2008 provides the with-Keyword, so one could instantiate without fluent interface as well:

var config = new Configuration() with { Color = "blue", Height = 1, Length = 2, Depth = 3 };

3) A better sample would result in stuff like:

// List<SpecialItem> _SpecialItems = new List<SpecialItem>();
SpecialItem.CreateColored("blue").Height(1).Length(2).Depth(3).AddTo(_SpecialItems);

That would demonstrate, how fluent interface reduce nesting. Compare to:

// List<SpecialItem> _SpecialItems = new List<SpecialItem>();
_SpecialItems.Add(new SpecialItem() with { Color = "blue", Height = 1, Length = 2, Depth = 3 });

Unfortunately the benefit "help from Intellisense" (a fluent interface supports fluent writing code) cannot be shown in an article, or would you like to add screenshots?

ErfinderDesRades (talk) 11:11, 15 December 2008 (UTC)[reply]


IMO the published sample is garbage. Chaining in itself does not make for readability and the ALT.NET community is severely abusing mere chaining with this misunderstanding. There's nothing less readable about

myObject.SetValueX(1);
myObject.SetValueY(2);

than

myObject.SetValueX(1).SetValueY(2);

In my opinion, this actually makes it less readable because these are distinct statements that are being slurred together.

I agree that the samples from ErfinderDesRades are better. Jon (talk) 09:52, 30 September 2009 (UTC)[reply]

PHP sample

[edit]

In the PHP sample, what is this part good for?

<?php
	session_start();
	error_reporting(E_ALL | E_USER_NOTICE);
	require_once 'classes/Loader.php';
	require_once 'config.php';
?>

Monad

[edit]

Shouldn't a reference to monad be included somewhere in this article? Dave Sexton (talk) 08:43, 26 July 2010 (UTC)[reply]

Fluent Interface vs Method Chains

[edit]

The article correctly states that a fluent interface entails more than just method chaining but then goes on to to show examples that solely use Method Chaining. This is misleading. The article and the examples could be improved to reflect a Fluent Interface' role in creating internal DSLs. This would make the distinction more clear. —Preceding unsigned comment added by 87.123.52.156 (talk) 08:46, 22 September 2010 (UTC)[reply]

Same comment from my side. The C++ example in fact does implement a fluent interface, but not so the other examples. One correct example is much more worth than a dozen of examples whereof only one really illustrates the point. Since nothing happened since this comment from 2010 I am going to remove the other examples. --Chiccodoro (talk) 11:15, 7 September 2012 (UTC)[reply]
The C++ example is also unnecessarily verbose. What about just deleting them all and adding a concise example in pseudo-code? As soon as you use a real language, people start getting all fanboyish and feel compelled to add their favorite one to the mix. — Preceding unsigned comment added by 82.9.176.129 (talk) 03:15, 18 December 2014 (UTC)[reply]

JQuery

[edit]

Is JQuery considered a fluent interface? If so, it should be referenced in this article.

Also, I'd like to echo the above topic's concern. This article doesn't make clear what the requirements for fluent interfaces are, beyond method chaining. —Preceding unsigned comment added by 208.91.1.14 (talk) 22:11, 27 October 2010 (UTC)[reply]


jQuery (note capitalization) definitely at least uses method chaining[1]. When you start with a selection of elements — e.g., $("li") to select all list items in the page — then most chained functions do indeed return the same collection (or perhaps a reduced/expanded collection) for further operations. Honestly, the Martin Fowler piece cited in the main article isn't terribly clear on what would be required to call something a "Fluent interface" either, though it does cite JMock as an example. Dave Brown (talk) 01:11, 8 April 2013 (UTC)[reply]

References

The non-existence of C# 3.5

[edit]

Regarding "With C# 3.5 and later there are more advanced method chaining techniques".

I don't think C# 3.5 exist; there is C# 3.0 and .NET Framework 3.5. Do you agree? --Mortense (talk) 03:09, 17 November 2010 (UTC)[reply]

Single-statement nature and debugging

[edit]

Issues raised in this comment were addressed, please see the 'Problems' section.

The article should elaborate on the problematic side of fluent style, which is debugging: fluent chains constitute a single statement or expression, which can be problematic when debugging, compared to more classic styles.

Typically, for many languages you are not able set breakpoints within a chain, and stepping will often be problematic.

There is also an issue with crash stack reports, in which a fluent chain will be treated as a single statement when the debug information is limited to statements (which for many languages is the case). That can make identifying which method call triggered an issue ambiguous if the same method is present more than once in a chain. —Preceding unsigned comment added by 88.174.31.159 (talk) 20:58, 7 January 2011 (UTC)[reply]

Problems > Subclasses

[edit]

In Java, Generics are used to enable subclassing without the subclasses having to implement all parent methods just to change the return type. JATL is a good example how it is done. — Preceding unsigned comment added by 94.143.89.37 (talk) 19:17, 25 December 2012 (UTC)[reply]

Minor Problem with the Java sample code

[edit]

With the font being used and the use of the variable name "l", it requires some thought to see that "l" is not "1" in pack( l ).

I tried changing "l" to "label" but that made the alignment of the grid method invocations look ... a bit ... ugly.

So I thought I'd just mention my problem with the "l" here. — Preceding unsigned comment added by 219.88.170.8 (talk) 19:44, 20 January 2014 (UTC)[reply]


The sample has a WRONG reference to Packer200, which is used for handling JAR. Its original reference was https://java.net/projects/packer but the java.net site closed. — Preceding unsigned comment added by 2001:F70:8C40:500:858F:B19C:A296:5FEE (talk) 14:02, 28 October 2021 (UTC)[reply]

Monad?

[edit]

Isn't this kind of style similar to a Monad? Should http://en.wikipedia.org/wiki/Monad_(functional_programming) be linked in the text? — Preceding unsigned comment added by Sukima (talkcontribs) 22:29, 21 May 2014 (UTC)[reply]

Re monads - this is a Javascript and purescript comparison showing this is just monads. https://github.com/pelotom/purescript-d3#example Here is the commentary: https://twitter.com/pelotom/status/483504492034269184 — Preceding unsigned comment added by 124.170.192.192 (talk) 04:36, 19 July 2014 (UTC)[reply]

Example Farm

[edit]

This is yet another computer science article that has turned into a large body of inconsistent and completely unecessary examples. The JavaScript section is (as usual) particularly egregious. A single pseudo-code example would more than suffice. — Preceding unsigned comment added by 82.9.176.129 (talk) 03:11, 18 December 2014 (UTC)[reply]

Not a Monad

[edit]

Bind is not the equivalent of a map operation, which is what is needed for method chaining. This is a misunderstanding of monads, and should be removed. — Preceding unsigned comment added by 98.189.26.19 (talk) 22:26, 12 February 2015 (UTC)[reply]

return this; vs. copy-on-write

[edit]

I think this article should mention the difference between two semantic variants of the fluent interface pattern that I've encountered: one where all mutators end with return this; and one (copy-on-write) where the implementing classes are immutable and the mutators return a modified copy. NeonMerlin 02:22, 1 July 2018 (UTC)[reply]

Java recursive generics

[edit]

The Java section has only usage examples from language libraries and doesn't show how you can build fluent interfaces yourself with recursive generics and other techniques. --Iamrcr (talk) 23:49, 20 February 2019 (UTC)[reply]

Java 8

[edit]

Should we list Java 8 Streams under the main fluent section as this is now builtin to the language? — Preceding unsigned comment added by Ginister (talkcontribs) 11:03, 27 March 2019 (UTC)[reply]

D programming language and UFCS

[edit]

In D language, there is this transparent feature called UFCS (Uniform Function Call Syntax), which for any call x.f(y, z), if the method f is not in the object / variable x, is translated to f(x, y, z) and the function f and its overloads are searched in all imported modules and symbols in the current scope. This allows fancy extensions, and Fluent like operations that can be extended by the user:

import std.stdio : writeln;
import std.algorithm.iteration : filter;
import std.range : iota;

void main()
    10.iota // returns numbers from 0 to 9
      // filter for even numbers
      .filter!(a => a % 2 == 0)
      .writeln(); // writes them to stdout

    // Traditional style:
    writeln(filter!(a => a % 2 == 0)
                   (iota(10)));
}

The two statements are exactly equivalent, and UFCS is basically a syntax sugar. However, it does allow extending any type, and adding fluent style operations.

class A {
 public:
  int a, b, c;
  auto setA(int a_) { a = a_; return this; }
}

auto setB(A t, int b_) { t.b = b_; return t; }

auto obj = A().setA(5).setB(8);

will work (as long as setB has access to the field b). setB doesn't even need to be in the same module. In fact due to powerful metaprogramming (mixins and mixin templates) and compile time introspection (compile traits), it is possible to automate generation of fluent interfaces for any class. Just my two cents. One my argue that this is just a syntax sugar, but so is 'Fluent' interface. It is just to save creating temporary variables with names, and making code readable from left to right, which UFCS enables. 81.6.34.172 (talk) 21:07, 29 April 2020 (UTC)[reply]