Misc

Why GPAL Uses Getters in the Fluent API

Why Getters

In a fluent chain every call is either configuring something or doing something. When a call does something with no configuration at all, parentheses suggest options that do not exist. A C# getter removes the parens and turns that absence into information -- a reader scanning the chain knows immediately that nothing is being set here. The compiler enforces the interface at each step either way, so there is no behavioral difference. The only payoff is clarity, and that is the entire point.

// Parens imply: something to configure.

// When there is nothing to configure,

// parens are noise that erodes that signal.


// Noisy:

GPAL.Browser()

.NextTab()

.Maximize()

.PageTop()


// Clean -- each call's shape tells you

// exactly what it is:

GPAL.Browser // factory getter

.GoTo(url) // method: needs a URL

.NextTab // action getter: just acts

.Maximize // action getter: just acts

.WithSelector(sel) // method: needs a selector

.PageTop // action getter: just acts

.LeftClick() // overloaded: can take a sel

NOTE

A GPAL getter is not a plain value property. It returns the next interface in the chain, exactly as a method call would -- the only difference is the call-site syntax.

Factory Getters - Entry Points

Factory getters are the static entry points on the GPAL class that return the first interface for each subsystem. Because they take no arguments -- the subsystem itself is the only thing being named -- they are getters. This means every GPAL chain starts the same way: GPAL.Something, never new Something() or GPAL.GetSomething(). One entry pattern for every subsystem, nothing to remember.

// Every GPAL subsystem starts with a getter.

// You never new() a GPAL object.


GPAL.Browser // start a browser chain

.GoTo(url) ...


GPAL.YouTube // start a YouTube chain

.WithCredentials(creds) ...


GPAL.AI // start an AI chain

.WithProvider(...) ...


GPAL.Selector // build a selector object

.WithCSS(".item")

.ToGPALObject();


// Also: GPAL.Logger, GPAL.Credentials,

// GPAL.GoogleSheets, GPAL.MagicHelper ...

NOTE

Browser, YouTube, AI, Logger, Credentials, GoogleSheets -- every subsystem entry is a getter on GPAL. If you can name the subsystem, you can start a chain.

Action Getters, Exceptions, and Why

Mid-chain action getters cover navigation (NextTab, PreviousTab, NextWindow, PreviousWindow), page control (PageTop, PageEnd, PageUp, PageDown, Back, Forward, Refresh), window state (Maximize, Minimize, Restore, FullScreen), and interaction mode switches (WithHardware, WithJavaScript, WithInfiniteScroll). InMainDom() is the one deliberate exception: it has no parameter, so by the rule it should be a getter. It stays a method because InIframe(), InShadowDom(), and InMainDom() form a visible family in a chain. Making one of them a getter while the others are methods would imply a distinction that does not exist. When following the rule would make the code less clear than breaking it, the rule yields.

// Mid-chain action getters:

GPAL.Browser

.Maximize // window size

.GoTo(url)

.NextTab // tab navigation

.PreviousWindow // window navigation

.PageEnd // scroll

.WithSelector(sel)

.WithHardware // interaction mode

.LeftClick()


// Exception -- InMainDom() stays a method:

GPAL.Browser

.InIframe(iframeSel) // method (has param)

.WithSelector(inner)

.FillInFrom("value")

.InMainDom() // no param, but method

.WithSelector(outer) // because In___() is

.LeftClick() // a visual family

NOTE

LeftClick() stays a method because it is overloaded -- LeftClick(selector) also exists. The rule only promotes a call to a getter when the no-parameter form is the only form. An overloaded method would produce ambiguous resolution as a getter, so it stays a method.

💬 Ask GPAL