Vad kallas det när man programmerar så här?

Permalänk
Medlem

Vad kallas det när man programmerar så här?

Jag har sett mycket kod som liknar så här.

@Push public class MyAppLayoutRouterLayout extends AppLayoutRouterLayout<LeftLayouts.LeftResponsiveHybrid> { /** * Do not initialize here. This will lead to NPEs */ private DefaultNotificationHolder notifications; private DefaultBadgeHolder badge; public MyAppLayoutRouterLayout() { notifications = new DefaultNotificationHolder(newStatus -> { }); badge = new DefaultBadgeHolder(5); for (int i = 1; i < 6; i++) { notifications.add(new DefaultNotification("Test title" + i, "A rather long test description ..............." + i)); } LeftNavigationItem menuEntry = new LeftNavigationItem("Menu", VaadinIcon.MENU.create(), View6.class); badge.bind(menuEntry.getBadge()); init(AppLayoutBuilder.get(LeftLayouts.LeftResponsiveHybrid.class) .withTitle("App Layout") .withAppBar(AppBarBuilder.get() .add(new NotificationButton<>(VaadinIcon.BELL, notifications)) .build()) .withAppMenu(LeftAppMenuBuilder.get() .addToSection(HEADER, new LeftHeaderItem("Menu-Header", "APP_LAYOUT_VERSION", "path/to/your/image"), new LeftClickableItem("Clickable Entry", VaadinIcon.COG.create(), clickEvent -> Notification.show("onClick ...")) ) .add(new LeftNavigationItem("Home", VaadinIcon.HOME.create(), View1.class), LeftSubMenuBuilder.get("My Submenu", VaadinIcon.PLUS.create()) .add(LeftSubMenuBuilder.get("My Submenu", VaadinIcon.PLUS.create()) .add(new LeftNavigationItem("Charts", VaadinIcon.SPLINE_CHART.create(), View2.class), new LeftNavigationItem("Contact", VaadinIcon.CONNECT.create(), View3.class), new LeftNavigationItem("More", VaadinIcon.COG.create(), View4.class)) .build(), new LeftNavigationItem("Contact1", VaadinIcon.CONNECT.create(), View3.class), new LeftNavigationItem("More1", VaadinIcon.COG.create(), View5.class)) .build(), menuEntry) .addToSection(FOOTER, new LeftClickableItem("Clickable Entry", VaadinIcon.COG.create(), clickEvent -> Notification.show("onClick ..."))) .build()) .build()); } }

https://appreciated-collection.herokuapp.com/app-layout/

//Just make sure the number of inputs of the next layer equals to the number of outputs in the previous layer. val conf = new NeuralNetConfiguration.Builder() .seed(12345) .weightInit(WeightInit.XAVIER) .updater(new AdaGrad(0.5)) .activation(Activation.RELU) .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT) .learningRate(0.05) .l2(0.0001) .list() //First hidden layer .layer(0, new DenseLayer.Builder() .nIn(784).nOut(250) .weightInit(WeightInit.XAVIER) .activation(Activation.RELU) .build()) //Second hidden layer .layer(1, new DenseLayer.Builder() .nIn(250).nOut(100) .weightInit(WeightInit.XAVIER) .activation(Activation.RELU) .build()) //Third hidden layer .layer(2, new DenseLayer.Builder() .nIn(100).nOut(50) .weightInit(WeightInit.XAVIER) .activation(Activation.RELU) .build()) //Output layer .layer(3, new OutputLayer.Builder() .nIn(50).nOut(10) .weightInit(WeightInit.XAVIER) .activation(Activation.SOFTMAX) .lossFunction(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) .build()) .build()

https://deeplearning4j.konduit.ai/getting-started/tutorials/f...

public class AreaChartExample extends Div { public AreaChartExample() { ApexCharts areaChart = ApexChartsBuilder.get() .withChart(ChartBuilder.get() .withType(Type.area) .withZoom(ZoomBuilder.get() .withEnabled(false) .build()) .build()) .withDataLabels(DataLabelsBuilder.get() .withEnabled(false) .build()) .withStroke(StrokeBuilder.get().withCurve(Curve.straight).build()) .withSeries(new Series<>("STOCK ABC", 10.0, 41.0, 35.0, 51.0, 49.0, 62.0, 69.0, 91.0, 148.0)) .withTitle(TitleSubtitleBuilder.get() .withText("Fundamental Analysis of Stocks") .withAlign(Align.left).build()) .withSubtitle(TitleSubtitleBuilder.get() .withText("Price Movements") .withAlign(Align.left).build()) .withLabels(IntStream.range(1, 10).boxed().map(day -> LocalDate.of(2000, 1, day).toString()).toArray(String[]::new)) .withXaxis(XAxisBuilder.get() .withType(XAxisType.datetime).build()) .withYaxis(YAxisBuilder.get() .withOpposite(true).build()) .withLegend(LegendBuilder.get().withHorizontalAlign(HorizontalAlign.left).build()) .build(); add(areaChart); setWidth("100%"); } }

https://appreciated-collection.herokuapp.com/apexcharts/

Mer kan hittas här:
https://appreciated-collection.herokuapp.com/

Är detta någon speciell teknik? Notera att dom avslutar alltid med .build() på slutet.

Permalänk
Medlem
Skrivet av heretic16:

Jag har sett mycket kod som liknar så här.

@Push public class MyAppLayoutRouterLayout extends AppLayoutRouterLayout<LeftLayouts.LeftResponsiveHybrid> { /** * Do not initialize here. This will lead to NPEs */ private DefaultNotificationHolder notifications; private DefaultBadgeHolder badge; public MyAppLayoutRouterLayout() { notifications = new DefaultNotificationHolder(newStatus -> { }); badge = new DefaultBadgeHolder(5); for (int i = 1; i < 6; i++) { notifications.add(new DefaultNotification("Test title" + i, "A rather long test description ..............." + i)); } LeftNavigationItem menuEntry = new LeftNavigationItem("Menu", VaadinIcon.MENU.create(), View6.class); badge.bind(menuEntry.getBadge()); init(AppLayoutBuilder.get(LeftLayouts.LeftResponsiveHybrid.class) .withTitle("App Layout") .withAppBar(AppBarBuilder.get() .add(new NotificationButton<>(VaadinIcon.BELL, notifications)) .build()) .withAppMenu(LeftAppMenuBuilder.get() .addToSection(HEADER, new LeftHeaderItem("Menu-Header", "APP_LAYOUT_VERSION", "path/to/your/image"), new LeftClickableItem("Clickable Entry", VaadinIcon.COG.create(), clickEvent -> Notification.show("onClick ...")) ) .add(new LeftNavigationItem("Home", VaadinIcon.HOME.create(), View1.class), LeftSubMenuBuilder.get("My Submenu", VaadinIcon.PLUS.create()) .add(LeftSubMenuBuilder.get("My Submenu", VaadinIcon.PLUS.create()) .add(new LeftNavigationItem("Charts", VaadinIcon.SPLINE_CHART.create(), View2.class), new LeftNavigationItem("Contact", VaadinIcon.CONNECT.create(), View3.class), new LeftNavigationItem("More", VaadinIcon.COG.create(), View4.class)) .build(), new LeftNavigationItem("Contact1", VaadinIcon.CONNECT.create(), View3.class), new LeftNavigationItem("More1", VaadinIcon.COG.create(), View5.class)) .build(), menuEntry) .addToSection(FOOTER, new LeftClickableItem("Clickable Entry", VaadinIcon.COG.create(), clickEvent -> Notification.show("onClick ..."))) .build()) .build()); } }

https://appreciated-collection.herokuapp.com/app-layout/

//Just make sure the number of inputs of the next layer equals to the number of outputs in the previous layer. val conf = new NeuralNetConfiguration.Builder() .seed(12345) .weightInit(WeightInit.XAVIER) .updater(new AdaGrad(0.5)) .activation(Activation.RELU) .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT) .learningRate(0.05) .l2(0.0001) .list() //First hidden layer .layer(0, new DenseLayer.Builder() .nIn(784).nOut(250) .weightInit(WeightInit.XAVIER) .activation(Activation.RELU) .build()) //Second hidden layer .layer(1, new DenseLayer.Builder() .nIn(250).nOut(100) .weightInit(WeightInit.XAVIER) .activation(Activation.RELU) .build()) //Third hidden layer .layer(2, new DenseLayer.Builder() .nIn(100).nOut(50) .weightInit(WeightInit.XAVIER) .activation(Activation.RELU) .build()) //Output layer .layer(3, new OutputLayer.Builder() .nIn(50).nOut(10) .weightInit(WeightInit.XAVIER) .activation(Activation.SOFTMAX) .lossFunction(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) .build()) .build()

https://deeplearning4j.konduit.ai/getting-started/tutorials/f...

public class AreaChartExample extends Div { public AreaChartExample() { ApexCharts areaChart = ApexChartsBuilder.get() .withChart(ChartBuilder.get() .withType(Type.area) .withZoom(ZoomBuilder.get() .withEnabled(false) .build()) .build()) .withDataLabels(DataLabelsBuilder.get() .withEnabled(false) .build()) .withStroke(StrokeBuilder.get().withCurve(Curve.straight).build()) .withSeries(new Series<>("STOCK ABC", 10.0, 41.0, 35.0, 51.0, 49.0, 62.0, 69.0, 91.0, 148.0)) .withTitle(TitleSubtitleBuilder.get() .withText("Fundamental Analysis of Stocks") .withAlign(Align.left).build()) .withSubtitle(TitleSubtitleBuilder.get() .withText("Price Movements") .withAlign(Align.left).build()) .withLabels(IntStream.range(1, 10).boxed().map(day -> LocalDate.of(2000, 1, day).toString()).toArray(String[]::new)) .withXaxis(XAxisBuilder.get() .withType(XAxisType.datetime).build()) .withYaxis(YAxisBuilder.get() .withOpposite(true).build()) .withLegend(LegendBuilder.get().withHorizontalAlign(HorizontalAlign.left).build()) .build(); add(areaChart); setWidth("100%"); } }

https://appreciated-collection.herokuapp.com/apexcharts/

Mer kan hittas här:
https://appreciated-collection.herokuapp.com/

Är detta någon speciell teknik? Notera att dom avslutar alltid med .build() på slutet.

"fluent" är väl nyckelordet, om jag förstår frågan rätt.

Permalänk
Medlem

Det är "Builder Pattern" som i dina exempel kortfattat går ut på att använda "method chaining" på en builder-klass för att bygga upp objekt istället för t.ex. en constructor.

Permalänk
Medlem

Rekommenderar boken Effective Java för en bra genomgång på det här och mycket annat

Permalänk
Medlem
Skrivet av Xenofonus:

Rekommenderar boken Effective Java för en bra genomgång på det här och mycket annat

Men sådant sätt är bara bra om man ska skriva bibliotek som någon annan ska använda. Eller kan man göra vanlig programmering med sådant också?

Permalänk
Medlem
Skrivet av heretic16:

Men sådant sätt är bara bra om man ska skriva bibliotek som någon annan ska använda. Eller kan man göra vanlig programmering med sådant också?

Kan och kan - man skall skriva kod som är läsbar. Helst ska du skriva kod som är så självförklarande att du slipper ha kommentarer. (Eftersom kommentarer kan bli föråldrade av att det blir en extra sak man behöver uppdatera när man ändrar en viss del i programmet, så det kan bli glömt och vips har man kommentarer som ljuger för näste stackars programmerare som skall göra en ändring i programmet)

Kan inte säga att det där faller under kategorin läsbar kod.

Permalänk
Medlem
Skrivet av evil penguin:

"fluent" är väl nyckelordet, om jag förstår frågan rätt.

jupp, "fluent": https://en.wikipedia.org/wiki/Fluent_interface
som använder sig av "method chaining": https://en.wikipedia.org/wiki/Method_chaining

Permalänk
Medlem

Detta är ett sätt att lösa det på. Elegant för användare av ett specifikt bibliotek då det är lätt att via tillgängliga publika metoder skaffa sig en överblick över vad man kan göra. Ett bra sätt att bygga ett publikt API helt enkelt.

Dock är det en del extrajobb att bygga upp den här hanteringen så om man ska bygga kod för en specifik uppgift som inte är ett publikt API för andra att nyttja så skulle jag själv inte använda det.

Däremot finns det en hel massa andra bra programmeringsmönster som man har stor nytta av att lära sig, eller som det heter på engelska "Design Patterns". Mycket av den kod man ser i Open Source-projekt bygger på ett eller flera av de mer standard design patterns som finns. Även Javas egna interna bibliotek. Helt enkelt ett recept för att lösa standardproblem så man själv inte behöver uppfinna hjulet gång på gång själv. Skaffa nån bra bok i ämnet eller kolla online. Exempelvis här:
https://www.geeksforgeeks.org/software-design-patterns/
Man behöver inte lära sig alla i detalj på en gång. Men skaffa en överblick och ha dom i minne att detaljstudera när ett specifikt problem uppenbarar sig. Då sätter man sig in i det specifika mönstret och löser uppgiften galant.

En sak att nämna är att design patterns är språkoberoende till störstadel. Dvs de går att tillämpa oavsett programmeringsspråk (i vart fall objektorienterade, och "normala" språk).

Permalänk
Medlem
Skrivet av heretic16:

Men sådant sätt är bara bra om man ska skriva bibliotek som någon annan ska använda. Eller kan man göra vanlig programmering med sådant också?

Nä definitivt bra för alla.

Just Builder pattern rekommenderas t ex om du har en klass med väldigt många valfria fält eller när du har så många fält att constructorn blir ett monster att anropa.

Då kan du använda fluid interface genom buildern pattern för att slippa anropa massa setters.