vojtamolda / Plotly.swift

Interactive data visualization library for Swift
https://vojtamolda.github.io/Plotly.swift/
MIT License
82 stars 8 forks source link

Create simple, human friendly initializers #1

Closed vojtamolda closed 4 years ago

vojtamolda commented 4 years ago

Automatically code-(de)generated initializers of all traces currently accept a ridiculously large number of arguments. On average it's about 50. To make it even worse Swift requires that the arguments follow the same order as the definition. This is very inconvenient and leads to below-average user experience in comparison to other Swift libraries.

In this specific case, behavior similar Python's keyword arguments would be preferable but it would require a change to Swift that's way above my competence level. Automatic completion built into XCode that usually saves the day isn't all too helpful because the parameter list is truncated and doesn't fit the screen.

One way to reduce this friction surface is a simplified init(...) method that accepts only a handful of the most frequent parameters. The idea is similar to what convenience init(...) provides for classes.

For example, the Scatter trace could be created via a constructor that is understandable without a deep dive into the (at the moment non-existent) documentation:

init(name: String? = nil, x: XData? = nil, y: YData? = nil,
     marker: Marker? = nil, line: Line? = nil, mode: Mode? = nil)

Especially to first time users, this looks much less intimidating than the full list of 46 parameters:

init(visible: Shared.Visible? = nil, showLegend: Bool? = nil, legendGroup: String? = nil,
     opacity: Double? = nil, name: String? = nil, uid: String? = nil, ids: [String]? = nil,
     customData: [String]? = nil, meta: ArrayOrAnything? = nil, selectedPoints: Anything? = nil,
     hoverInfo: Shared.HoverInfo? = nil, hoverLabel: Shared.HoverLabel? = nil,
     stream: Shared.Stream? = nil, transforms: [Shared.Transform]? = nil,
     uiRevision: Anything? = nil, x: XData? = nil, x0: Anything? = nil, dx: Double? = nil,
     y: YData? = nil, y0: Anything? = nil, dy: Double? = nil, stackGroup: String? = nil,
     orientation: Shared.Orientation? = nil, groupNormalization: GroupNormalization? = nil,
     stackGaps: StackGaps? = nil, text: ArrayOrString? = nil, textTemplate: ArrayOrString? = nil,
     hoverText: ArrayOrString? = nil, mode: Shared.Mode? = nil, hoverOn: Shared.HoverOn? = nil,
     hoverTemplate: ArrayOrString? = nil, line: SplineSmoothedDashedLine? = nil,
     connectGaps: Bool? = nil, clipOnAxis: Bool? = nil, fill: Shared.Fill? = nil,
     fillColor: Color? = nil, marker: Shared.GradientMarker? = nil, selected: Selected? = nil,
     unselected: Unselected? = nil, textPosition: Shared.TextPosition? = nil,
     textFont: Shared.Font? = nil, xError: Shared.Error? = nil, yError: Shared.Error? = nil,
     xCalendar: Shared.Calendar? = nil, yCalendar: Shared.Calendar? = nil,
     xAxis: SubPlotID? = nil, yAxis: SubPlotID? = nil)

My gut feel is that the reduced initializer covers about 70% of use cases. More complicated charts that require tweaking of other properties can be created by crating var and modifying the rest of the properties on the following lines in arbitrary ordering:

var scatterPlot = Scatter(name: "Simpler Initializer", x: [1, 2], y: [3, 4])
scatterPlot.hoverText = ["Three", "Four"]
vojtamolda commented 4 years ago

Implemented!