SlideShare a Scribd company logo
1 of 24
There is just too much grunt work
in programming
Imagine if you could
write all of this
public class DatabaseConfiguration {
private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
@Bean(destroyMethod = "close")
public DataSource dataSource(DataSourceProperties dataSourceProperties, CustomProperties customProperties) {
log.debug("Initializing datasource...");
HikariConfig config = new HikariConfig();
config.setDataSourceClassName(dataSourceProperties.getDriverClassName());
config.addDataSourceProperty("url", dataSourceProperties.getUrl());
config.addDataSourceProperty("user", dataSourceProperties.getUsername());
config.addDataSourceProperty("password", dataSourceProperties.getPassword() == null ? "" : dataSourceProperties.getPassword());
// mysql specific
config.addDataSourceProperty("cachePrepStmts", customProperties.getDatasource().isCachePrepStmts());
config.addDataSourceProperty("prepStmtCacheSize", customProperties.getDatasource().getPrepStmtCacheSize());
config.addDataSourceProperty("prepStmtCacheSqlLimit", customProperties.getDatasource().getPrepStmtCacheSqlLimit());
config.addDataSourceProperty("useServerPrepStmts", customProperties.getDatasource().isUseServerPrepStmts());
return new HikariDataSource(config);
}
@Bean
public SpringLiquibase liquibase(DataSource dataSource, DataSourceProperties dataSourceProperties, LiquibaseProperties liquibaseProperties) {
log.debug("Initializing liquibase...");
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource);
liquibase.setChangeLog("classpath:liquibase/db-changelog.xml");
return liquibase;
}
@Entity
@Table(name = "Device")
public class Device implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Size(min = 1, max = 20)
@Column(name = "name")
private String name;
@NotNull
@Size(min = 1, max = 20)
@Column(name = "gsmNumber")
private String gsmNumber;
@NotNull
@Size(min = 5, max = 5)
@Column(name = "imei")
private String imei;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "role")
private Role role;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "status")
private DeviceStatus status;
@ManyToOne
@JoinColumn(name = "hotelId")
private Hotel hotel;
@NotNull
@Column(name = "isBroken")
private Boolean isBroken;
@NotNull
@Column(name = "lastLocation")
@Embedded
@AttributeOverrides({@AttributeOverride(name = "latitude", column = @Column(name = "lastLocationLatitude")),
@AttributeOverride(name = "longitude", column = @Column(name = "lastLocationLongitude"))})
private GpsCoordinates lastLocation;
@NotNull
@Column(name = "timestamp")
private ZonedDateTime timestamp;
@NotNull
@Column(name = "isDeleted")
private Boolean isDeleted;
public Long getId() {
return id;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Device other = (Device) obj;
if ((id == null && other.id != null) || !id.equals(other.id))
return false;
if ((name == null && other.name != null) || !name.equals(other.name))
return false;
if ((gsmNumber == null && other.gsmNumber != null) || !gsmNumber.equals(other.gsmNumber))
return false;
if ((imei == null && other.imei != null) || !imei.equals(other.imei))
return false;
if ((role == null && other.role != null) || !role.equals(other.role))
return false;
if ((status == null && other.status != null) || !status.equals(other.status))
return false;
if ((hotel == null && other.hotel != null) || !hotel.equals(other.hotel))
return false;
if ((isBroken == null && other.isBroken != null) || !isBroken.equals(other.isBroken))
return false;
if ((lastLocation == null && other.lastLocation != null) || !lastLocation.equals(other.lastLocation))
return false;
if ((timestamp == null && other.timestamp != null) || !timestamp.equals(other.timestamp))
return false;
if ((isDeleted == null && other.isDeleted != null) || !isDeleted.equals(other.isDeleted))
return false;
return true;
}
@RestController
@RequestMapping("/api/")
public class DeviceApi {
private final Logger log = LoggerFactory.getLogger(DeviceApi.class);
@Inject
private DeviceRepository deviceRepository;
@RequestMapping(value = "/device", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@PreAuthorize("hasAuthority('ROLE_SUPER_ADMIN')")
public ResponseEntity<Void> createDevice(@Valid @RequestBody DeviceCreateDTO request, @ApiIgnore @AuthenticationPrincipal Long principalId) {
log.debug("POST /device {}", request);
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
@RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional(readOnly = true)
@PreAuthorize("hasAuthority('ROLE_HOTEL_ADMIN')")
public ResponseEntity<ViewDeviceResponse> viewDevice(@PathVariable Long deviceId) {
log.debug("GET /device/{}", deviceId);
final Optional<Device> result = deviceRepository.viewDevice(deviceId);
if (result.isPresent()) {
return ResponseEntity.ok().body(convertToViewDeviceResponse(result.get()));
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@RequestMapping(value = "/device", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@PreAuthorize("hasAuthority('ROLE_HOTEL_ADMIN')")
public ResponseEntity<Void> updateDevice(@Valid @RequestBody DeviceEditDTO request, @ApiIgnore @AuthenticationPrincipal Long principalId) {
log.debug("PUT /device {}", request);
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
@RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@PreAuthorize("hasAuthority('ROLE_SUPER_ADMIN')")
public ResponseEntity<Void> deleteDevice(@PathVariable Long deviceId) {
log.debug("DELETE /device/{}", deviceId);
deviceRepository.deleteDevice(deviceId);
return ResponseEntity.ok().build();
}
@RequestMapping(value = "/device/all", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional(readOnly = true)
@PreAuthorize("hasAuthority('ROLE_SUPER_ADMIN')")
public ResponseEntity<PagedDTO<DevicesAllResponse>> devicesAll(@RequestParam(value = "hotelId", required = false) Optional<Long> hotelId,
@RequestParam(value = "status", required = false) Optional<DeviceStatus> status, @RequestParam("drop") Integer drop,
@RequestParam("take") Integer take) {
log.debug("GET /device/all");
final List<DeviceHotelTuple> result = deviceRepository.devicesAllPaged(Optional.ofNullable(hotelId), Optional.ofNullable(status), drop, take);
final Long totalCount = deviceRepository.countDevicesAll(Optional.ofNullable(hotelId), Optional.ofNullable(status));
return ResponseEntity.ok().body(new
PagedDTO<DevicesAllResponse>(result.stream().map(this::convertToDevicesAllResponse).collect(Collectors.toList()), totalCount));
}
@Override
public List<Device> devicesAllSearchResults(Optional<Long> hotelId, Optional<String> imei, Optional<String> name, Optional<String> gsmNumber,
Optional<DeviceStatus> status) {
log.trace(".devicesAllSearchResults(hotelId: {}, imei, name: {}, gsmNumber: {}, status: {})", hotelId, name, gsmNumber, status);
final QDevice device = QDevice.device;
return factory.select(device).from(device)
.where(new BooleanBuilder().and(hotelId.isPresent() ? device.hotel.id.eq(hotelId.get()) : null).and(imei.isPresent() ? device.imei.eq(imei.get()) : null)
.and(name.isPresent() ? device.name.eq(name.get()) : null).and(gsmNumber.isPresent() ? device.gsmNumber.eq(gsmNumber.get()) : null)
.and(status.isPresent() ? device.status.eq(status.get()) : null).and(hotelId.isPresent() ? device.hotel.id.eq(hotelId.get()) : null))
.fetch();
}
@Override
public List<Device> devicesHotel(Optional<DeviceStatus> status) {
log.trace(".devicesHotel(status: {})", status);
final QDevice device = QDevice.device;
return factory.select(device).from(device).where(status.isPresent() ? device.status.eq(status.get()) : null).fetch();
}
@Override
public List<Device> devicesHotelSearchResults(Optional<Long> hotelId, Optional<String> imei, Optional<String> name, Optional<String> gsmNumber,
Optional<DeviceStatus> status) {
log.trace(".devicesHotelSearchResults(hotelId: {}, imei, name: {}, gsmNumber: {}, status: {})", hotelId, name, gsmNumber, status);
final QDevice device = QDevice.device;
return factory.select(device).from(device)
.where(new BooleanBuilder().and(hotelId.isPresent() ? device.hotel.id.eq(hotelId.get()) : null).and(imei.isPresent() ? device.imei.eq(imei.get()) : null)
.and(name.isPresent() ? device.name.eq(name.get()) : null).and(gsmNumber.isPresent() ? device.gsmNumber.eq(gsmNumber.get()) : null)
.and(status.isPresent() ? device.status.eq(status.get()) : null))
.fetch();
}
Device model(
name optional text[min 1, max 20]
gsmNumber text[min 1, max 20]
imei text[min 5, max 5, sensitive]
role Role
status DeviceStatus
hotel optional Hotel
isBroken boolean
lastLocation gpsCoordinates
timestamp datetime
isDeleted boolean
)
In only this much
You can now — with Sifu
The challenge:
• Higher level abstractions = loss of low level control
• Focus only on a specific domain
• No flexibility
• Resulting code can’t be treated as machine code
Current approaches:
• Force you to write your own patterns
• Way too general
• Generate code that is marked as "generated"
• Generate code that can be inherited
• Generated code is sub-optimal
The Sifu way:
• High level DSL for client/server data-driven applications
• Patterns and good practises included
• Translates to code that can be freely changed and extended
• Code looks like it was written by an experienced developer
Sifu elements:
SifuDSL
SifuCompiler
SifuLinker
SifuDSL:
• DSL specially designed for web and mobile developers
• Describe your backend and client like you would describe it to your peer
• Say no to incomplete and out of date specifications nobody reads
SifuCompiler:
• Does the dull work for you.
• Checks your specifications for errors and applies all of the best practices.
• It's smart it adds everything you will need to the code base so it's there when
you need it.
SifuLinker:
• Transforms your specification to maintainable code.
• The same code as you would write it yourself!
• It can support the tech stack of your choice.
You own the whole codebase!
Mix the code you created with Sifu and manually without the fear of losing any
while changing the code base.
Keep the specs up to date and benefit from using Sifu throughout the application
lifecycle.
Up to 90% of codebase can be created
with Sifu alone!
Sifu specs become a developer
communication tool
Codebase is consistent and implements
all of the best practices
Now it's time for you to focus on fun stuff
—
Create the code that really makes a
difference for the team
Visit: codesifu.com/getstarted

More Related Content

What's hot

HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)croquiscom
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the ASTJarrod Overson
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Coscup2021 - useful abstractions at rust and it's practical usage
Coscup2021 - useful abstractions at rust and it's practical usageCoscup2021 - useful abstractions at rust and it's practical usage
Coscup2021 - useful abstractions at rust and it's practical usageWayne Tsai
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」matuura_core
 
Coscup2021-rust-toturial
Coscup2021-rust-toturialCoscup2021-rust-toturial
Coscup2021-rust-toturialWayne Tsai
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns ReconsideredAlex Miller
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS ProgrammersDavid Rodenas
 
外部環境への依存をテストする
外部環境への依存をテストする外部環境への依存をテストする
外部環境への依存をテストするShunsuke Maeda
 
JPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APIJPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APItvaleev
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legione-Legion
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 

What's hot (20)

HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
Your code is not a string
Your code is not a stringYour code is not a string
Your code is not a string
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Coscup2021 - useful abstractions at rust and it's practical usage
Coscup2021 - useful abstractions at rust and it's practical usageCoscup2021 - useful abstractions at rust and it's practical usage
Coscup2021 - useful abstractions at rust and it's practical usage
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
 
Coscup2021-rust-toturial
Coscup2021-rust-toturialCoscup2021-rust-toturial
Coscup2021-rust-toturial
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Green dao
Green daoGreen dao
Green dao
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns Reconsidered
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
外部環境への依存をテストする
外部環境への依存をテストする外部環境への依存をテストする
外部環境への依存をテストする
 
JPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APIJPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream API
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 

Viewers also liked

Sean McConnell_Resume_16 (1) (1)
Sean McConnell_Resume_16 (1) (1)Sean McConnell_Resume_16 (1) (1)
Sean McConnell_Resume_16 (1) (1)Sean McConnell
 
Power point_VS_Projet de recherche (final)
Power point_VS_Projet de recherche (final)Power point_VS_Projet de recherche (final)
Power point_VS_Projet de recherche (final)Vincent Sylvestre
 
Témoignages s-parcours-divers-scientifiques (1)
Témoignages s-parcours-divers-scientifiques (1)Témoignages s-parcours-divers-scientifiques (1)
Témoignages s-parcours-divers-scientifiques (1)CDILEF
 
~$Thaly macias
~$Thaly macias~$Thaly macias
~$Thaly maciasnathaly7mo
 
Tutorial eclipse 1
Tutorial eclipse 1Tutorial eclipse 1
Tutorial eclipse 1ivan ramirez
 
θανατικη ποινη 10
θανατικη ποινη 10θανατικη ποινη 10
θανατικη ποινη 10Marinathomaas
 
εθισμοσ υπερβολικη χρηση
εθισμοσ υπερβολικη χρησηεθισμοσ υπερβολικη χρηση
εθισμοσ υπερβολικη χρησηMarinathomaas
 
105 9-14 加工機夾治具刀具解決方案介紹
105 9-14 加工機夾治具刀具解決方案介紹105 9-14 加工機夾治具刀具解決方案介紹
105 9-14 加工機夾治具刀具解決方案介紹Rich Man
 
C13 - Political Attitudes of The Arab World
C13 -  Political Attitudes of The Arab WorldC13 -  Political Attitudes of The Arab World
C13 - Political Attitudes of The Arab WorldFatin Nazihah Aziz
 

Viewers also liked (14)

Sean McConnell_Resume_16 (1) (1)
Sean McConnell_Resume_16 (1) (1)Sean McConnell_Resume_16 (1) (1)
Sean McConnell_Resume_16 (1) (1)
 
Power point_VS_Projet de recherche (final)
Power point_VS_Projet de recherche (final)Power point_VS_Projet de recherche (final)
Power point_VS_Projet de recherche (final)
 
Annonce emt pm
Annonce emt pmAnnonce emt pm
Annonce emt pm
 
axilogia
axilogiaaxilogia
axilogia
 
Témoignages s-parcours-divers-scientifiques (1)
Témoignages s-parcours-divers-scientifiques (1)Témoignages s-parcours-divers-scientifiques (1)
Témoignages s-parcours-divers-scientifiques (1)
 
Surf fishing tips
Surf fishing tipsSurf fishing tips
Surf fishing tips
 
~$Thaly macias
~$Thaly macias~$Thaly macias
~$Thaly macias
 
Tutorial eclipse 1
Tutorial eclipse 1Tutorial eclipse 1
Tutorial eclipse 1
 
θανατικη ποινη 10
θανατικη ποινη 10θανατικη ποινη 10
θανατικη ποινη 10
 
εθισμοσ υπερβολικη χρηση
εθισμοσ υπερβολικη χρησηεθισμοσ υπερβολικη χρηση
εθισμοσ υπερβολικη χρηση
 
Certificate
CertificateCertificate
Certificate
 
105 9-14 加工機夾治具刀具解決方案介紹
105 9-14 加工機夾治具刀具解決方案介紹105 9-14 加工機夾治具刀具解決方案介紹
105 9-14 加工機夾治具刀具解決方案介紹
 
C13 - Political Attitudes of The Arab World
C13 -  Political Attitudes of The Arab WorldC13 -  Political Attitudes of The Arab World
C13 - Political Attitudes of The Arab World
 
Rks tpkdbrev1
Rks   tpkdbrev1Rks   tpkdbrev1
Rks tpkdbrev1
 

Similar to Why Sifu

Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 
deepjs - tools for better programming
deepjs - tools for better programmingdeepjs - tools for better programming
deepjs - tools for better programmingnomocas
 
Cnam azure 2014 mobile services
Cnam azure 2014   mobile servicesCnam azure 2014   mobile services
Cnam azure 2014 mobile servicesAymeric Weinbach
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testingVisual Engineering
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"LogeekNightUkraine
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptVisual Engineering
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster DivingRonnBlack
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gearsdion
 
DAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docx
DAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docxDAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docx
DAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docxtheodorelove43763
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Paco de la Cruz
 

Similar to Why Sifu (20)

Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
deepjs - tools for better programming
deepjs - tools for better programmingdeepjs - tools for better programming
deepjs - tools for better programming
 
Cnam azure 2014 mobile services
Cnam azure 2014   mobile servicesCnam azure 2014   mobile services
Cnam azure 2014 mobile services
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster Diving
 
An intro to cqrs
An intro to cqrsAn intro to cqrs
An intro to cqrs
 
Introduccion a Jasmin
Introduccion a JasminIntroduccion a Jasmin
Introduccion a Jasmin
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
All things that are not code
All things that are not codeAll things that are not code
All things that are not code
 
DAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docx
DAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docxDAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docx
DAOFactory.javaDAOFactory.javapublicclassDAOFactory{ this .docx
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
Anti patterns
Anti patternsAnti patterns
Anti patterns
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 

Recently uploaded

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
software engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptxsoftware engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptxnada99848
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 

Recently uploaded (20)

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
software engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptxsoftware engineering Chapter 5 System modeling.pptx
software engineering Chapter 5 System modeling.pptx
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 

Why Sifu

  • 1. There is just too much grunt work in programming
  • 2. Imagine if you could write all of this
  • 3. public class DatabaseConfiguration { private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class); @Bean(destroyMethod = "close") public DataSource dataSource(DataSourceProperties dataSourceProperties, CustomProperties customProperties) { log.debug("Initializing datasource..."); HikariConfig config = new HikariConfig(); config.setDataSourceClassName(dataSourceProperties.getDriverClassName()); config.addDataSourceProperty("url", dataSourceProperties.getUrl()); config.addDataSourceProperty("user", dataSourceProperties.getUsername()); config.addDataSourceProperty("password", dataSourceProperties.getPassword() == null ? "" : dataSourceProperties.getPassword()); // mysql specific config.addDataSourceProperty("cachePrepStmts", customProperties.getDatasource().isCachePrepStmts()); config.addDataSourceProperty("prepStmtCacheSize", customProperties.getDatasource().getPrepStmtCacheSize()); config.addDataSourceProperty("prepStmtCacheSqlLimit", customProperties.getDatasource().getPrepStmtCacheSqlLimit()); config.addDataSourceProperty("useServerPrepStmts", customProperties.getDatasource().isUseServerPrepStmts()); return new HikariDataSource(config); } @Bean public SpringLiquibase liquibase(DataSource dataSource, DataSourceProperties dataSourceProperties, LiquibaseProperties liquibaseProperties) { log.debug("Initializing liquibase..."); SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource(dataSource); liquibase.setChangeLog("classpath:liquibase/db-changelog.xml"); return liquibase; }
  • 4. @Entity @Table(name = "Device") public class Device implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Size(min = 1, max = 20) @Column(name = "name") private String name; @NotNull @Size(min = 1, max = 20) @Column(name = "gsmNumber") private String gsmNumber; @NotNull @Size(min = 5, max = 5) @Column(name = "imei") private String imei; @NotNull @Enumerated(EnumType.STRING) @Column(name = "role") private Role role;
  • 5. @NotNull @Enumerated(EnumType.STRING) @Column(name = "status") private DeviceStatus status; @ManyToOne @JoinColumn(name = "hotelId") private Hotel hotel; @NotNull @Column(name = "isBroken") private Boolean isBroken; @NotNull @Column(name = "lastLocation") @Embedded @AttributeOverrides({@AttributeOverride(name = "latitude", column = @Column(name = "lastLocationLatitude")), @AttributeOverride(name = "longitude", column = @Column(name = "lastLocationLongitude"))}) private GpsCoordinates lastLocation; @NotNull @Column(name = "timestamp") private ZonedDateTime timestamp; @NotNull @Column(name = "isDeleted") private Boolean isDeleted; public Long getId() { return id; }
  • 6. @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final Device other = (Device) obj; if ((id == null && other.id != null) || !id.equals(other.id)) return false; if ((name == null && other.name != null) || !name.equals(other.name)) return false; if ((gsmNumber == null && other.gsmNumber != null) || !gsmNumber.equals(other.gsmNumber)) return false; if ((imei == null && other.imei != null) || !imei.equals(other.imei)) return false; if ((role == null && other.role != null) || !role.equals(other.role)) return false; if ((status == null && other.status != null) || !status.equals(other.status)) return false; if ((hotel == null && other.hotel != null) || !hotel.equals(other.hotel)) return false; if ((isBroken == null && other.isBroken != null) || !isBroken.equals(other.isBroken)) return false; if ((lastLocation == null && other.lastLocation != null) || !lastLocation.equals(other.lastLocation)) return false; if ((timestamp == null && other.timestamp != null) || !timestamp.equals(other.timestamp)) return false; if ((isDeleted == null && other.isDeleted != null) || !isDeleted.equals(other.isDeleted)) return false; return true; }
  • 7. @RestController @RequestMapping("/api/") public class DeviceApi { private final Logger log = LoggerFactory.getLogger(DeviceApi.class); @Inject private DeviceRepository deviceRepository; @RequestMapping(value = "/device", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @Timed @Transactional @PreAuthorize("hasAuthority('ROLE_SUPER_ADMIN')") public ResponseEntity<Void> createDevice(@Valid @RequestBody DeviceCreateDTO request, @ApiIgnore @AuthenticationPrincipal Long principalId) { log.debug("POST /device {}", request); return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @Timed @Transactional(readOnly = true) @PreAuthorize("hasAuthority('ROLE_HOTEL_ADMIN')") public ResponseEntity<ViewDeviceResponse> viewDevice(@PathVariable Long deviceId) { log.debug("GET /device/{}", deviceId); final Optional<Device> result = deviceRepository.viewDevice(deviceId); if (result.isPresent()) { return ResponseEntity.ok().body(convertToViewDeviceResponse(result.get())); } return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @RequestMapping(value = "/device", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE) @Timed @Transactional @PreAuthorize("hasAuthority('ROLE_HOTEL_ADMIN')") public ResponseEntity<Void> updateDevice(@Valid @RequestBody DeviceEditDTO request, @ApiIgnore @AuthenticationPrincipal Long principalId) { log.debug("PUT /device {}", request); return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); }
  • 8. @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE) @Timed @Transactional @PreAuthorize("hasAuthority('ROLE_SUPER_ADMIN')") public ResponseEntity<Void> deleteDevice(@PathVariable Long deviceId) { log.debug("DELETE /device/{}", deviceId); deviceRepository.deleteDevice(deviceId); return ResponseEntity.ok().build(); } @RequestMapping(value = "/device/all", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @Timed @Transactional(readOnly = true) @PreAuthorize("hasAuthority('ROLE_SUPER_ADMIN')") public ResponseEntity<PagedDTO<DevicesAllResponse>> devicesAll(@RequestParam(value = "hotelId", required = false) Optional<Long> hotelId, @RequestParam(value = "status", required = false) Optional<DeviceStatus> status, @RequestParam("drop") Integer drop, @RequestParam("take") Integer take) { log.debug("GET /device/all"); final List<DeviceHotelTuple> result = deviceRepository.devicesAllPaged(Optional.ofNullable(hotelId), Optional.ofNullable(status), drop, take); final Long totalCount = deviceRepository.countDevicesAll(Optional.ofNullable(hotelId), Optional.ofNullable(status)); return ResponseEntity.ok().body(new PagedDTO<DevicesAllResponse>(result.stream().map(this::convertToDevicesAllResponse).collect(Collectors.toList()), totalCount)); }
  • 9. @Override public List<Device> devicesAllSearchResults(Optional<Long> hotelId, Optional<String> imei, Optional<String> name, Optional<String> gsmNumber, Optional<DeviceStatus> status) { log.trace(".devicesAllSearchResults(hotelId: {}, imei, name: {}, gsmNumber: {}, status: {})", hotelId, name, gsmNumber, status); final QDevice device = QDevice.device; return factory.select(device).from(device) .where(new BooleanBuilder().and(hotelId.isPresent() ? device.hotel.id.eq(hotelId.get()) : null).and(imei.isPresent() ? device.imei.eq(imei.get()) : null) .and(name.isPresent() ? device.name.eq(name.get()) : null).and(gsmNumber.isPresent() ? device.gsmNumber.eq(gsmNumber.get()) : null) .and(status.isPresent() ? device.status.eq(status.get()) : null).and(hotelId.isPresent() ? device.hotel.id.eq(hotelId.get()) : null)) .fetch(); } @Override public List<Device> devicesHotel(Optional<DeviceStatus> status) { log.trace(".devicesHotel(status: {})", status); final QDevice device = QDevice.device; return factory.select(device).from(device).where(status.isPresent() ? device.status.eq(status.get()) : null).fetch(); } @Override public List<Device> devicesHotelSearchResults(Optional<Long> hotelId, Optional<String> imei, Optional<String> name, Optional<String> gsmNumber, Optional<DeviceStatus> status) { log.trace(".devicesHotelSearchResults(hotelId: {}, imei, name: {}, gsmNumber: {}, status: {})", hotelId, name, gsmNumber, status); final QDevice device = QDevice.device; return factory.select(device).from(device) .where(new BooleanBuilder().and(hotelId.isPresent() ? device.hotel.id.eq(hotelId.get()) : null).and(imei.isPresent() ? device.imei.eq(imei.get()) : null) .and(name.isPresent() ? device.name.eq(name.get()) : null).and(gsmNumber.isPresent() ? device.gsmNumber.eq(gsmNumber.get()) : null) .and(status.isPresent() ? device.status.eq(status.get()) : null)) .fetch(); }
  • 10. Device model( name optional text[min 1, max 20] gsmNumber text[min 1, max 20] imei text[min 5, max 5, sensitive] role Role status DeviceStatus hotel optional Hotel isBroken boolean lastLocation gpsCoordinates timestamp datetime isDeleted boolean ) In only this much
  • 11. You can now — with Sifu
  • 12. The challenge: • Higher level abstractions = loss of low level control • Focus only on a specific domain • No flexibility • Resulting code can’t be treated as machine code
  • 13. Current approaches: • Force you to write your own patterns • Way too general • Generate code that is marked as "generated" • Generate code that can be inherited • Generated code is sub-optimal
  • 14. The Sifu way: • High level DSL for client/server data-driven applications • Patterns and good practises included • Translates to code that can be freely changed and extended • Code looks like it was written by an experienced developer
  • 16. SifuDSL: • DSL specially designed for web and mobile developers • Describe your backend and client like you would describe it to your peer • Say no to incomplete and out of date specifications nobody reads
  • 17. SifuCompiler: • Does the dull work for you. • Checks your specifications for errors and applies all of the best practices. • It's smart it adds everything you will need to the code base so it's there when you need it.
  • 18. SifuLinker: • Transforms your specification to maintainable code. • The same code as you would write it yourself! • It can support the tech stack of your choice.
  • 19. You own the whole codebase! Mix the code you created with Sifu and manually without the fear of losing any while changing the code base. Keep the specs up to date and benefit from using Sifu throughout the application lifecycle.
  • 20. Up to 90% of codebase can be created with Sifu alone!
  • 21. Sifu specs become a developer communication tool
  • 22. Codebase is consistent and implements all of the best practices
  • 23. Now it's time for you to focus on fun stuff — Create the code that really makes a difference for the team

Editor's Notes

  1. I think you will agree with us, programming is harder than it should be. Even when you know exactly what you want to build and how you want to built it. You need to write it!
  2. Just imagine!
  3. this
  4. and this
  5. and this
  6. and this
  7. and this
  8. and this
  9. and this
  10. But at the same time all the information you need to do it can be written like this. So why wouldn’t you just write it like this?
  11. But at the same time all the information you need to do it can be written like this. So why wouldn’t you just write it like this?
  12. There are a few challenges: - the fundamental problem with higher level abstractions is the loss of low level control - with a higher level of abstractions, the more you have to focus on a specific domain - it’s impossible to do everything with purely high level abstractions if you want to solve real world use cases - generated code still needs to be read and modified by humans, so it cannot be treated as machine code (e.g. has to be optimized)
  13. Current approaches: - force you to write your own patterns, which implies a significant amount of work from your side - are too general, meaning the effort required is not significantly better than writing pure code - provide you with generated code that is marked as "generated", meaning that it will be overwritten each time the tool is used and as such cannot be edited Or - provides you with generated code that can be inherited, allowing some level of modification but only in a way that original developers predicted - generated code is usually sub-optimal, meaning that the code is not human readable and often includes a lot of code that will never be used
  14. Our approach - Instead of focusing on business domain when building our DSL we have focused on the developer domain. In our case those are client/server data driven applications. - We have included all of the proven industry patterns and best practised in the tool so developers can start using it in a matter of minutes. - Resulting code can be freely changed and extended, and most importantly code looks like it was written by an experienced developer.
  15. We have based Sifu around 3 key components.
  16. What does this DSL support? Specification data is used to build an application model. Describe common high level concepts, such as: - models - security constraints - finely-grained APIs - UI that binds to the specified APIs - dependencies to external services like OAuth providers, payment processors, Google maps, S3 file storage etc… - ...
  17. It does just that, all of the dull work, so you can use your creativity.
  18. Generate the code via technology specific templates: - Smart templates: are crucial to making sure that the generated code is optimized, e.g. it needs to be exactly as an (experienced) developer would have written it - Include "production" ready features by default (e.g. logging, monitoring, security configuration, development profile,...)
  19. Yes, you own all of the codebase that was made using Sifu or customly added. If you at any point want to ditch Sifu you can do it easily. You simply own all of the code at the end of the day.
  20. Early users reported some exciting stats.
  21. We didn’t expect this to happen, but is seems that teams are using our specs as a form of communication, as it’s much easier to grasp the whole project when looking at far less lines of code.
  22. Visit: codesifu.com/getstarted Follow us: https://twitter.com/sifuHQ and https://www.facebook.com/sifuHQ/