SlideShare a Scribd company logo
Yaroslav Voloshchuk && Aleksey Yashchenko
Grammarly
False Simplicity
of Frontend Applications
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
• Who we are?
• Software Engineers @ Grammarly
• Working on …
• Past
• Browser Extension
• Present
• Web Editor
• Desktop Editor

Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
Our Talk: Overview
• [Done] Who we are
• => Overview (this slide :D)
• Complexity assessment mistake: why it happens?
• How to get it right?
• How to deal with complexity on the code level?

Our Talk
• [Done] Who we are
• [Done] Overview
• => Complexity assessment mistake: why it happens?
• How to get it right?
• How to deal with complexity on the code level?

1. Why and how it happens
• People don’t understand the problem they are solving
• Incomplete requirements
• Edge cases not taken into account
• 3rd party libraries/components are being used
• …
Inherent problems
complexity
2. The process
• Planning and resource allocation
• Choosing approach, architecture, tools
• Coding
• Release :(
• …
2. The process
• …
• Details appear in the process ‘out of the blue’
• It’s a small change!
• Let’s add one `if`
• [Repeat]
• Code => Spaghetti
• Release?
2. The process
• …
• Details appear in the process ‘out of the blue’
• It’s a small change!
• Let’s add one `if`
• [Repeat]
• Code => Spaghetti
• Release… :(
Can you just add this button please?
Shouldn’t be too hard!
2. The process
• …
• Details appear in the process ‘out of the blue’
• It’s a small change!
• Let’s add one `if`
• [Repeat]
• Code => Spaghetti
• Release… :(
Can you just add this button please?
Shouldn’t be too hard!
2. The process
• …
• Details appear in the process ‘out of the blue’
• It’s a small change!
• Let’s add one `if`
• [Repeat]
• Code => Spaghetti
• Eternal release… soon :( Release… :(
3.1. Technical Results
• Unsupportable, write-only code
• Instant legacy in a new product
• Undermining architectural effort; non-optimal solution
completely ruins the architecture



3.1. Product Results
• Bugs
• Unexpected behavior
• A lot of product areas are underdeveloped
• Team’s moral & spirit is affected

Okay, smarty, what to do?
• Get complexity right
• Address it on the code level
Our Talk
• [Done] Who we are
• [Done] Overview
• [Done] Complexity assessment mistake: why it
happens?
• => How to get it right?
• How to deal with complexity on the code level?

Describe the problem in more details
• Talk to colleagues, specialists, 

non-specialists, and to the debug duck
• Run a requirements testing with QA engineers
• Ask how to break a feature before you write it,
brainstorm corner cases
• Ask how a feature will develop in 1-2 years from now
• Look how it’s done by competitors, think why
Describe the problem in more details:Tools
• => Design mockups & prototyping
• Build models
• Plain old multileveled list
• Mind maps
• Draw a state chart (state diagram) with events and
transitions
• User story mapping
Describe the problem in more details:Tools
• Design mockups & prototyping
• => Build models
• Plain old multileveled list
• Mind maps
• Draw a state chart (state diagram) with events and
transitions
• User story mapping
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
Describe the problem in more details:Tools
• Design mockups & prototyping
• Build models
• => Plain old multileveled list
• Mind maps
• Draw a state chart (state diagram) with events and
transitions
• User story mapping
Describe the problem in more details:Tools
• Design mockups & prototyping
• Build models
• Plain old multileveled list
• => Mind maps
• Draw a state chart (state diagram) with events and
transitions
• User story mapping
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
Describe the problem in more details:Tools
• Design mockups & prototyping
• Build models
• Plain old multileveled list
• Mind maps
• => Draw a state chart (state diagram) with events and
transitions
• User story mapping
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
Describe the problem in more details:Tools
• Design mockups & prototyping
• Build models
• Plain old multileveled list
• Mind maps
• Draw a state chart (state diagram) with events and
transitions
• => User story mapping (well, we don’t use it :))
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
• …
• You name it!







Describe the problem in more details
Complexity Assessment:
But don’t go waterfall!
Okay… 

Houston, we have
a complex problem,
what now?
Deal with it.
Our Talk
• [Done] Who we are
• [Done] Overview
• [Done] Complexity assessment mistake: why it happens?
• [Done] How to get it right?
• => How to deal with complexity on the code level?
–Edsger W. Dijkstra
“The art of programming is 

the art of organizing complexity”
–Anonymous
“Programming is all about composition”
Complexity?
Complexity?
• Wikipedia: In software engineering, programming
complexity is a measure of the interactions of the
various elements of the software.
• Level of entropy
• More: https://en.wikipedia.org/wiki/Complex_system

Where it came from?
• Essential complexity
• Input
• Output
• Accidental complexity
• Everything else we created



- Brooks, Fred (1986).“No Silver Bullet” 

• Coupling 

how tightly a module is related to others
• Cohesion 

how closely all the routines in a module support it’s
central purpose













Characteristics
• Readability
• Maintainability
• Branching (Cyclomatic complexity)
• Size (LOC)
• More buzzwords: 

https://en.wikipedia.org/wiki/Programming_complexity

Characteristics
It occurs at different levels
• Statements
• Methods
• Modules / Classes
• App / Subsystems
• Product / Requirements
Structural
Behavioral
It occurs at different levels
• Statements
• Methods
• Modules / Classes
• App / Subsystems
• Product / Requirements
Structural
Behavioral
Conquering Complexity
Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"
1. Statements
• const vs let

Use const everywhere
• for, while, if, break => 

foreach, map, reduce, filter, find, ...
• Try, Option

Idiomatic handling for empty values and errors
• With this you mostly don’t need defensive
programming
Idiomatic handling for empty values and errors
export function parseConfig(
base: AppConfig,
localConfig: Option<string>
): AppConfig {
return localConfig
.flatMap(config =>
Try.of(() => JSON.parse(config)).recover(() => window.atob(config)).toOption()
)
.flatMap(
parsedConfig =>
iots
.validate(parsedConfig, ConfigType)
.map(validConfig => merge(base, validConfig)) // Load app with custom config
)
.getOrElse(base)
}
2. Functions/Methods
• Prefer pure functions
• Prefer polymorphism to if statements
• Single responsibility
• Don’t break invariants
• Use composition with functions. 

They are first class citizens (thus: memoization, strategy,
pipeline, etc)
• Make it understandable without reading the method body
Prefer polymorphism to if statements
////// Don’t
function logMessage(message: string) {
remoteLoggerSink.send(message)
if (Config.printToConsole) {
console.log('LOG: ' + message)
}
}
////// Do
function logToRemote(message: string) {
remoteLoggerSink.send(message)
}
function logWithConsole(message: string) {
logToRemote(message)
console.log('LOG: ' + message)
}
const logMessage = Config.printToConsole ? logWithConsole : logToRemote
2. Functions/Methods
• Prefer pure functions
• Prefer polymorphism to if statements
• Single responsibility
• Don’t break invariants
• Use composition with functions. 

They are first class citizens (thus: memoization, strategy,
pipeline, etc)
• Make it understandable without reading the method body
Don’t break invariants
/// Don’t
const alert = Alerts.createAlert(alertData)
// ...
// then
alert.register(positionManager)
/// Do
const alert = Alerts.createAlert(alertData, positionManager)
2. Functions/Methods
• Prefer pure functions
• Prefer polymorphism to if statements
• Single responsibility
• Don’t break invariants
• Use composition with functions. 

They are first class citizens (thus: memoization, strategy,
pipeline, etc)
• Make it understandable without reading the method body
Make it understandable without reading the
method body
// Don't
function parse(data) {
// 20 LOC body to read
}
// Do
function parseConfig(configJson: string): Try<Config> {
// Whatever
}
3. Modules/Classes #0
• Use Types
• Use Types
• Use Types
• If in doubt => Use Types



3. Modules/Classes #0
• Use Types
• Use Types
• Use Types
• If in doubt => Use Types



Flow
TypeScript
Elm
PureScript
OCaml (BuckleScript)
…
3. Modules/Classes #1
• Liskov substitution principle
3. Modules/Classes #1: SOLID
• Single responsibility principle
• Open/closed principle
• Liskov substitution principle
• Interface segregation principle
• Dependency inversion principle
Single responsibility principle
const alerts: Alert[] = alertsManager.allAlerts()
// Don’t
const scoreString: string = calculateScore(alerts)
// Do
const score: Score = calculateScore(alerts)
const scoreString: string = jsonSerializer(score)
Open/closed principle
class TrackingClient {
// ...
track(event: TrackingEvent) {
fetch(this._endpoing, { /* payload */ })
}
}
class TrackingClient {
// ...
constructor(private _fetch = fetch) {
}
track(logEntry: TrackingEvent) {
this._fetch(this._endpoing, { /* payload */ })
}
}
Liskov substitution principle
interface ImmutablePoint {
readonly x: number
readonly y: number
}
// Wrong, violates contract
interface MutablePoint extends ImmutablePoint {
x: number
y: number
}
3. Modules/Classes #1: SOLID
• Single responsibility principle
• Open/closed principle
• Liskov substitution principle
• Interface segregation principle
• Dependency inversion principle
Dependency inversion principle
namespace Bad {
class A {}
class B {
// Direct dependency creates stronger coupling
constructor(param: A) {}
}
}
namespace Good {
interface A {}
class B {
// Dependency on abstraction, allows any impl here
constructor(param: A) {}
}
class AImpl implements A {}
}
3. Modules/Classes #2
• Data hiding/encapsulation
• Separation of concerns
• Composition over inheritance
• Invariance in types
• Algebraic data types
enum RequestState {
loading,
ready,
error
}
interface Loading {
state: RequestState.loading
}
interface Ready {
state: RequestState.ready
data: string
}
interface Error {
state: RequestState.error
error: any
}
type Request = Loading | Ready | Error
function proccesRequest(request: Request) {
switch (request.state) {
case RequestState.loading: return console.info('request in progress')
case RequestState.ready: return console.log('response', request.data)
case RequestState.error: return console.error('error =(', request.error)
default:
const state: never = request
throw new Error('Unexpected state')
}
}
Algebraic Data Types
buzzwords…
YAGNI
DRY
Stable Dependencies Principle
Stable Abstractions Principle
KISS
MDA
Monoids
GRASP
Code Generation
Currying
Continuations
4. Subsystems/Apps
• Don’t reinvent the wheel:There is an app library for that!
• Grab a good runtime library 

(ramda, immutable.js, lodash-fp, etc, still not clear for TS thou)
• Read more papers, e.g. 

https://github.com/papers-we-love/papers-we-love
• Use existing design patterns which address your problem
• Use suitable data structures instead of arrays/objects
• Use frameworks/libraries that fit your task
Behavioral Complexity
Behavioral Complexity
• Callbacks hell
• PubSub aka Emitter hell
• FRP comes to the rescue!
• Event Streams (Signals/Observables) > Events
• RxJS, Bacon.js, Kefir, Highland
hoveredMarks = this.options.scrollContainer
.map(scroll => scroll.getOrElseL(() => this.quill.root))
.switchMap(container =>
Observable.merge(
Observable.fromEvent(container, 'mouseenter').mapTo(true),
Observable.fromEvent(container, 'mouseleave').mapTo(false)
)
)
.switchMap(
inside =>
inside
? Observable.merge(
this.options.contentUpdated.mapTo(None),
this.options.scrollPositionChanged.mapTo(None),
Observable.fromEvent<MouseEvent>(this.quill.root, 'mousemove')
.auditTime(50)
.map(e => {
const node = document.elementFromPoint(e.clientX, e.clientY)
const blot = Quill.find(node, true) as Blot
return !blot || blot instanceof Quill
? None
: this._getMarksByBlot(blot)
})
)
: Observable.of(None).delay(200)
)
.distinctUntilChanged(this._optionMarksEqual)
.share()
.startWith(None)
Fin.
Questions?
Yaroslav Voloshchuk
@wenqer
LI:yaroslavvoloshchuk
Aleksey Yashchenko
@tuxslayer
FB/LI:tuxslayer
Further Reading
Further reading 

Articles on Requirements & Complexity
• Programming complexity https://en.wikipedia.org/wiki/
Programming_complexity
• Cyclomatic complexity https://en.wikipedia.org/wiki/
Cyclomatic_complexity
• No Silver Bullet http://www.cs.nott.ac.uk/~pszcah/G51ISS/Documents/
NoSilverBullet.html
• SOLID https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
• The Coming Software Apocalypse https://www.theatlantic.com/
technology/archive/2017/09/saving-the-world-from-code/540393
• User story mapping https://www.scrumalliance.org/community/articles/
2013/august/creating-an-agile-roadmap-using-story-mapping
Further reading

Useful papers, articles and tech
• Papers we love 

https://github.com/papers-we-love/papers-we-love
• FP vs OOP 

http://blog.cleancoder.com/uncle-bob/2014/11/24/
FPvsOO.html
• AirBnb Sketch App 

https://github.com/airbnb/react-sketchapp
• FSM 

https://en.wikipedia.org/wiki/Finite-state_machine
Further reading

Books and stuff
• Code Complete
• FRP https://www.manning.com/books/functional-reactive-programming
• Refactoring: Improving the Design of Existing Code
• UML Distilled: A Brief Guide to the Standard Object Modeling Language
• Head First Design Patterns
• Learning JavaScript Design Patterns
• TypeScript Deep Dive https://www.gitbook.com/book/basarat/typescript/details
• Functional JavaScript http://shop.oreilly.com/product/0636920028857.do
• FP in Scala https://www.manning.com/books/functional-programming-in-scala
• PureScript https://leanpub.com/purescript/read
• Learn You a Haskell for Great Good http://learnyouahaskell.com

More Related Content

What's hot (20)

ODP
Gatling
Gaurav Shukla
 
PDF
Sharing the pain using Protractor
Anand Bagmar
 
PDF
Behavior-Driven Development and Automation Testing Using Cucumber Framework W...
KMS Technology
 
PPTX
Lets cook cucumber !!
vodQA
 
PDF
Automated Testing in Angular Slides
Jim Lynch
 
PDF
"Production Driven Development", Serhii Kalinets
Fwdays
 
PDF
"Technical Challenges behind Visual IDE for React Components" Tetiana Mandziuk
Fwdays
 
PPT
Jasmine - A BDD test framework for JavaScript
Sumanth krishna
 
PPTX
BDD from QA side
Anton Shapin
 
PDF
Capybara testing
Futureworkz
 
PDF
Unit Testing your React / Redux app (@BucharestJS)
Alin Pandichi
 
PPTX
Protractor overview
Abhishek Yadav
 
PPTX
Migration from AngularJS to Angular
Aleks Zinevych
 
PPT
Behavior Driven Development by Example
Nalin Goonawardana
 
PDF
Meetup React Sanca - 29/11/18 - React Testing
Augusto Lazaro
 
PDF
Advanced A/B Testing at Wix - Aviran Mordo and Sagy Rozman, Wix.com
DevOpsDays Tel Aviv
 
PPTX
Load testing with Visual Studio and Azure - Andrew Siemer
Andrew Siemer
 
PDF
Getting By Without "QA"
Dave King
 
PDF
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Codemotion
 
PPTX
Testing Java EE apps with Arquillian
Ivan Ivanov
 
Gatling
Gaurav Shukla
 
Sharing the pain using Protractor
Anand Bagmar
 
Behavior-Driven Development and Automation Testing Using Cucumber Framework W...
KMS Technology
 
Lets cook cucumber !!
vodQA
 
Automated Testing in Angular Slides
Jim Lynch
 
"Production Driven Development", Serhii Kalinets
Fwdays
 
"Technical Challenges behind Visual IDE for React Components" Tetiana Mandziuk
Fwdays
 
Jasmine - A BDD test framework for JavaScript
Sumanth krishna
 
BDD from QA side
Anton Shapin
 
Capybara testing
Futureworkz
 
Unit Testing your React / Redux app (@BucharestJS)
Alin Pandichi
 
Protractor overview
Abhishek Yadav
 
Migration from AngularJS to Angular
Aleks Zinevych
 
Behavior Driven Development by Example
Nalin Goonawardana
 
Meetup React Sanca - 29/11/18 - React Testing
Augusto Lazaro
 
Advanced A/B Testing at Wix - Aviran Mordo and Sagy Rozman, Wix.com
DevOpsDays Tel Aviv
 
Load testing with Visual Studio and Azure - Andrew Siemer
Andrew Siemer
 
Getting By Without "QA"
Dave King
 
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Codemotion
 
Testing Java EE apps with Arquillian
Ivan Ivanov
 

Similar to Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications" (20)

KEY
Refactoring RIA Unleashed 2011
Jesse Warden
 
PDF
Good Coding Practices with JavaScript
🏁 Pierre-Henry Soria 💡
 
PDF
Writing code for people
Alexey Ivanov
 
PPTX
Software Development Essential Skills
John Choi
 
PPTX
Rediscovering Modularity
Chris Chedgey
 
PPTX
Shut Up And Eat Your Veg
Garth Gilmour
 
PPTX
Programming in the large
Naveenkumar Muguda
 
PPTX
2 Years of Real World FP at REA
kenbot
 
PPTX
Clean code, Feb 2012
cobyst
 
PPS
CS101- Introduction to Computing- Lecture 44
Bilal Ahmed
 
PDF
Managing JavaScript Complexity
Jarrod Overson
 
PPTX
Improving Code Quality Through Effective Review Process
Dr. Syed Hassan Amin
 
PDF
A Summary of “Out of the Tar Pit” by Jacob Beers
Ortus Solutions, Corp
 
PDF
Patterns, Code Smells, and The Pragmattic Programmer
Jason McCreary
 
PDF
How to write good quality code
Hayden Bleasel
 
PDF
Excavating the knowledge of our ancestors
Uwe Friedrichsen
 
PPTX
Restructuring- improving the modularity of an existing code-base
Chris Chedgey
 
PDF
Refactoring JavaScript turning bad code into good code First Edition Burchard
simbajdzikie4
 
PDF
Tricks for Isolated Architecture in Ruby - Sergey Kukunin
Ruby Meditation
 
PDF
[DevDay2018] Let’s all get along. Clean Code please! - By: Christophe K. Ngo,...
DevDay Da Nang
 
Refactoring RIA Unleashed 2011
Jesse Warden
 
Good Coding Practices with JavaScript
🏁 Pierre-Henry Soria 💡
 
Writing code for people
Alexey Ivanov
 
Software Development Essential Skills
John Choi
 
Rediscovering Modularity
Chris Chedgey
 
Shut Up And Eat Your Veg
Garth Gilmour
 
Programming in the large
Naveenkumar Muguda
 
2 Years of Real World FP at REA
kenbot
 
Clean code, Feb 2012
cobyst
 
CS101- Introduction to Computing- Lecture 44
Bilal Ahmed
 
Managing JavaScript Complexity
Jarrod Overson
 
Improving Code Quality Through Effective Review Process
Dr. Syed Hassan Amin
 
A Summary of “Out of the Tar Pit” by Jacob Beers
Ortus Solutions, Corp
 
Patterns, Code Smells, and The Pragmattic Programmer
Jason McCreary
 
How to write good quality code
Hayden Bleasel
 
Excavating the knowledge of our ancestors
Uwe Friedrichsen
 
Restructuring- improving the modularity of an existing code-base
Chris Chedgey
 
Refactoring JavaScript turning bad code into good code First Edition Burchard
simbajdzikie4
 
Tricks for Isolated Architecture in Ruby - Sergey Kukunin
Ruby Meditation
 
[DevDay2018] Let’s all get along. Clean Code please! - By: Christophe K. Ngo,...
DevDay Da Nang
 
Ad

More from Fwdays (20)

PDF
"Mastering UI Complexity: State Machines and Reactive Patterns at Grammarly",...
Fwdays
 
PDF
"Effect, Fiber & Schema: tactical and technical characteristics of Effect.ts"...
Fwdays
 
PPTX
"Computer Use Agents: From SFT to Classic RL", Maksym Shamrai
Fwdays
 
PPTX
"Як ми переписали Сільпо на Angular", Євген Русаков
Fwdays
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PDF
"Validation and Observability of AI Agents", Oleksandr Denisyuk
Fwdays
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PPTX
"Co-Authoring with a Machine: What I Learned from Writing a Book on Generativ...
Fwdays
 
PPTX
"Human-AI Collaboration Models for Better Decisions, Faster Workflows, and Cr...
Fwdays
 
PDF
"AI is already here. What will happen to your team (and your role) tomorrow?"...
Fwdays
 
PPTX
"Is it worth investing in AI in 2025?", Alexander Sharko
Fwdays
 
PDF
''Taming Explosive Growth: Building Resilience in a Hyper-Scaled Financial Pl...
Fwdays
 
PDF
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
PDF
"Database isolation: how we deal with hundreds of direct connections to the d...
Fwdays
 
PDF
"Scaling in space and time with Temporal", Andriy Lupa .pdf
Fwdays
 
PPTX
"Provisioning via DOT-Chain: from catering to drone marketplaces", Volodymyr ...
Fwdays
 
PPTX
" Observability with Elasticsearch: Best Practices for High-Load Platform", A...
Fwdays
 
PPTX
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
Fwdays
 
PPTX
"Istio Ambient Mesh in production: our way from Sidecar to Sidecar-less",Hlib...
Fwdays
 
"Mastering UI Complexity: State Machines and Reactive Patterns at Grammarly",...
Fwdays
 
"Effect, Fiber & Schema: tactical and technical characteristics of Effect.ts"...
Fwdays
 
"Computer Use Agents: From SFT to Classic RL", Maksym Shamrai
Fwdays
 
"Як ми переписали Сільпо на Angular", Євген Русаков
Fwdays
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
"Validation and Observability of AI Agents", Oleksandr Denisyuk
Fwdays
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
"Co-Authoring with a Machine: What I Learned from Writing a Book on Generativ...
Fwdays
 
"Human-AI Collaboration Models for Better Decisions, Faster Workflows, and Cr...
Fwdays
 
"AI is already here. What will happen to your team (and your role) tomorrow?"...
Fwdays
 
"Is it worth investing in AI in 2025?", Alexander Sharko
Fwdays
 
''Taming Explosive Growth: Building Resilience in a Hyper-Scaled Financial Pl...
Fwdays
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
"Database isolation: how we deal with hundreds of direct connections to the d...
Fwdays
 
"Scaling in space and time with Temporal", Andriy Lupa .pdf
Fwdays
 
"Provisioning via DOT-Chain: from catering to drone marketplaces", Volodymyr ...
Fwdays
 
" Observability with Elasticsearch: Best Practices for High-Load Platform", A...
Fwdays
 
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
Fwdays
 
"Istio Ambient Mesh in production: our way from Sidecar to Sidecar-less",Hlib...
Fwdays
 
Ad

Recently uploaded (20)

PPTX
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
PPT
Interview paper part 3, It is based on Interview Prep
SoumyadeepGhosh39
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
Women in Automation Presents: Reinventing Yourself — Bold Career Pivots That ...
DianaGray10
 
PPTX
MSP360 Backup Scheduling and Retention Best Practices.pptx
MSP360
 
PDF
Log-Based Anomaly Detection: Enhancing System Reliability with Machine Learning
Mohammed BEKKOUCHE
 
PDF
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
PDF
Persuasive AI: risks and opportunities in the age of digital debate
Speck&Tech
 
PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PDF
Empowering Cloud Providers with Apache CloudStack and Stackbill
ShapeBlue
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
Smart Air Quality Monitoring with Serrax AQM190 LITE
SERRAX TECHNOLOGIES LLP
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PPTX
Darren Mills The Migration Modernization Balancing Act: Navigating Risks and...
AWS Chicago
 
PPTX
Top Managed Service Providers in Los Angeles
Captain IT
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PDF
Ampere Offers Energy-Efficient Future For AI And Cloud
ShapeBlue
 
PDF
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
PDF
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
Interview paper part 3, It is based on Interview Prep
SoumyadeepGhosh39
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Women in Automation Presents: Reinventing Yourself — Bold Career Pivots That ...
DianaGray10
 
MSP360 Backup Scheduling and Retention Best Practices.pptx
MSP360
 
Log-Based Anomaly Detection: Enhancing System Reliability with Machine Learning
Mohammed BEKKOUCHE
 
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
Persuasive AI: risks and opportunities in the age of digital debate
Speck&Tech
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
Empowering Cloud Providers with Apache CloudStack and Stackbill
ShapeBlue
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
Smart Air Quality Monitoring with Serrax AQM190 LITE
SERRAX TECHNOLOGIES LLP
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
Darren Mills The Migration Modernization Balancing Act: Navigating Risks and...
AWS Chicago
 
Top Managed Service Providers in Los Angeles
Captain IT
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
Ampere Offers Energy-Efficient Future For AI And Cloud
ShapeBlue
 
Human-centred design in online workplace learning and relationship to engagem...
Tracy Tang
 
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 

Алексей Ященко и Ярослав Волощук "False simplicity of front-end applications"

  • 1. Yaroslav Voloshchuk && Aleksey Yashchenko Grammarly False Simplicity of Frontend Applications
  • 3. • Who we are? • Software Engineers @ Grammarly • Working on … • Past • Browser Extension • Present • Web Editor • Desktop Editor

  • 5. Our Talk: Overview • [Done] Who we are • => Overview (this slide :D) • Complexity assessment mistake: why it happens? • How to get it right? • How to deal with complexity on the code level?

  • 6. Our Talk • [Done] Who we are • [Done] Overview • => Complexity assessment mistake: why it happens? • How to get it right? • How to deal with complexity on the code level?

  • 7. 1. Why and how it happens • People don’t understand the problem they are solving • Incomplete requirements • Edge cases not taken into account • 3rd party libraries/components are being used • …
  • 9. 2. The process • Planning and resource allocation • Choosing approach, architecture, tools • Coding • Release :( • …
  • 10. 2. The process • … • Details appear in the process ‘out of the blue’ • It’s a small change! • Let’s add one `if` • [Repeat] • Code => Spaghetti • Release?
  • 11. 2. The process • … • Details appear in the process ‘out of the blue’ • It’s a small change! • Let’s add one `if` • [Repeat] • Code => Spaghetti • Release… :( Can you just add this button please? Shouldn’t be too hard!
  • 12. 2. The process • … • Details appear in the process ‘out of the blue’ • It’s a small change! • Let’s add one `if` • [Repeat] • Code => Spaghetti • Release… :( Can you just add this button please? Shouldn’t be too hard!
  • 13. 2. The process • … • Details appear in the process ‘out of the blue’ • It’s a small change! • Let’s add one `if` • [Repeat] • Code => Spaghetti • Eternal release… soon :( Release… :(
  • 14. 3.1. Technical Results • Unsupportable, write-only code • Instant legacy in a new product • Undermining architectural effort; non-optimal solution completely ruins the architecture
 

  • 15. 3.1. Product Results • Bugs • Unexpected behavior • A lot of product areas are underdeveloped • Team’s moral & spirit is affected

  • 16. Okay, smarty, what to do? • Get complexity right • Address it on the code level
  • 17. Our Talk • [Done] Who we are • [Done] Overview • [Done] Complexity assessment mistake: why it happens? • => How to get it right? • How to deal with complexity on the code level?

  • 18. Describe the problem in more details • Talk to colleagues, specialists, 
 non-specialists, and to the debug duck • Run a requirements testing with QA engineers • Ask how to break a feature before you write it, brainstorm corner cases • Ask how a feature will develop in 1-2 years from now • Look how it’s done by competitors, think why
  • 19. Describe the problem in more details:Tools • => Design mockups & prototyping • Build models • Plain old multileveled list • Mind maps • Draw a state chart (state diagram) with events and transitions • User story mapping
  • 20. Describe the problem in more details:Tools • Design mockups & prototyping • => Build models • Plain old multileveled list • Mind maps • Draw a state chart (state diagram) with events and transitions • User story mapping
  • 22. Describe the problem in more details:Tools • Design mockups & prototyping • Build models • => Plain old multileveled list • Mind maps • Draw a state chart (state diagram) with events and transitions • User story mapping
  • 23. Describe the problem in more details:Tools • Design mockups & prototyping • Build models • Plain old multileveled list • => Mind maps • Draw a state chart (state diagram) with events and transitions • User story mapping
  • 25. Describe the problem in more details:Tools • Design mockups & prototyping • Build models • Plain old multileveled list • Mind maps • => Draw a state chart (state diagram) with events and transitions • User story mapping
  • 27. Describe the problem in more details:Tools • Design mockups & prototyping • Build models • Plain old multileveled list • Mind maps • Draw a state chart (state diagram) with events and transitions • => User story mapping (well, we don’t use it :))
  • 29. • … • You name it!
 
 
 
 Describe the problem in more details
  • 31. Okay… 
 Houston, we have a complex problem, what now?
  • 33. Our Talk • [Done] Who we are • [Done] Overview • [Done] Complexity assessment mistake: why it happens? • [Done] How to get it right? • => How to deal with complexity on the code level?
  • 34. –Edsger W. Dijkstra “The art of programming is 
 the art of organizing complexity” –Anonymous “Programming is all about composition”
  • 36. Complexity? • Wikipedia: In software engineering, programming complexity is a measure of the interactions of the various elements of the software. • Level of entropy • More: https://en.wikipedia.org/wiki/Complex_system

  • 37. Where it came from? • Essential complexity • Input • Output • Accidental complexity • Everything else we created
 
 - Brooks, Fred (1986).“No Silver Bullet” 

  • 38. • Coupling 
 how tightly a module is related to others • Cohesion 
 how closely all the routines in a module support it’s central purpose
 
 
 
 
 
 
 Characteristics
  • 39. • Readability • Maintainability • Branching (Cyclomatic complexity) • Size (LOC) • More buzzwords: 
 https://en.wikipedia.org/wiki/Programming_complexity
 Characteristics
  • 40. It occurs at different levels • Statements • Methods • Modules / Classes • App / Subsystems • Product / Requirements Structural Behavioral
  • 41. It occurs at different levels • Statements • Methods • Modules / Classes • App / Subsystems • Product / Requirements Structural Behavioral
  • 44. 1. Statements • const vs let
 Use const everywhere • for, while, if, break => 
 foreach, map, reduce, filter, find, ... • Try, Option
 Idiomatic handling for empty values and errors • With this you mostly don’t need defensive programming
  • 45. Idiomatic handling for empty values and errors export function parseConfig( base: AppConfig, localConfig: Option<string> ): AppConfig { return localConfig .flatMap(config => Try.of(() => JSON.parse(config)).recover(() => window.atob(config)).toOption() ) .flatMap( parsedConfig => iots .validate(parsedConfig, ConfigType) .map(validConfig => merge(base, validConfig)) // Load app with custom config ) .getOrElse(base) }
  • 46. 2. Functions/Methods • Prefer pure functions • Prefer polymorphism to if statements • Single responsibility • Don’t break invariants • Use composition with functions. 
 They are first class citizens (thus: memoization, strategy, pipeline, etc) • Make it understandable without reading the method body
  • 47. Prefer polymorphism to if statements ////// Don’t function logMessage(message: string) { remoteLoggerSink.send(message) if (Config.printToConsole) { console.log('LOG: ' + message) } } ////// Do function logToRemote(message: string) { remoteLoggerSink.send(message) } function logWithConsole(message: string) { logToRemote(message) console.log('LOG: ' + message) } const logMessage = Config.printToConsole ? logWithConsole : logToRemote
  • 48. 2. Functions/Methods • Prefer pure functions • Prefer polymorphism to if statements • Single responsibility • Don’t break invariants • Use composition with functions. 
 They are first class citizens (thus: memoization, strategy, pipeline, etc) • Make it understandable without reading the method body
  • 49. Don’t break invariants /// Don’t const alert = Alerts.createAlert(alertData) // ... // then alert.register(positionManager) /// Do const alert = Alerts.createAlert(alertData, positionManager)
  • 50. 2. Functions/Methods • Prefer pure functions • Prefer polymorphism to if statements • Single responsibility • Don’t break invariants • Use composition with functions. 
 They are first class citizens (thus: memoization, strategy, pipeline, etc) • Make it understandable without reading the method body
  • 51. Make it understandable without reading the method body // Don't function parse(data) { // 20 LOC body to read } // Do function parseConfig(configJson: string): Try<Config> { // Whatever }
  • 52. 3. Modules/Classes #0 • Use Types • Use Types • Use Types • If in doubt => Use Types
 

  • 53. 3. Modules/Classes #0 • Use Types • Use Types • Use Types • If in doubt => Use Types
 
 Flow TypeScript Elm PureScript OCaml (BuckleScript) …
  • 54. 3. Modules/Classes #1 • Liskov substitution principle
  • 55. 3. Modules/Classes #1: SOLID • Single responsibility principle • Open/closed principle • Liskov substitution principle • Interface segregation principle • Dependency inversion principle
  • 56. Single responsibility principle const alerts: Alert[] = alertsManager.allAlerts() // Don’t const scoreString: string = calculateScore(alerts) // Do const score: Score = calculateScore(alerts) const scoreString: string = jsonSerializer(score)
  • 57. Open/closed principle class TrackingClient { // ... track(event: TrackingEvent) { fetch(this._endpoing, { /* payload */ }) } } class TrackingClient { // ... constructor(private _fetch = fetch) { } track(logEntry: TrackingEvent) { this._fetch(this._endpoing, { /* payload */ }) } }
  • 58. Liskov substitution principle interface ImmutablePoint { readonly x: number readonly y: number } // Wrong, violates contract interface MutablePoint extends ImmutablePoint { x: number y: number }
  • 59. 3. Modules/Classes #1: SOLID • Single responsibility principle • Open/closed principle • Liskov substitution principle • Interface segregation principle • Dependency inversion principle
  • 60. Dependency inversion principle namespace Bad { class A {} class B { // Direct dependency creates stronger coupling constructor(param: A) {} } } namespace Good { interface A {} class B { // Dependency on abstraction, allows any impl here constructor(param: A) {} } class AImpl implements A {} }
  • 61. 3. Modules/Classes #2 • Data hiding/encapsulation • Separation of concerns • Composition over inheritance • Invariance in types • Algebraic data types
  • 62. enum RequestState { loading, ready, error } interface Loading { state: RequestState.loading } interface Ready { state: RequestState.ready data: string } interface Error { state: RequestState.error error: any } type Request = Loading | Ready | Error function proccesRequest(request: Request) { switch (request.state) { case RequestState.loading: return console.info('request in progress') case RequestState.ready: return console.log('response', request.data) case RequestState.error: return console.error('error =(', request.error) default: const state: never = request throw new Error('Unexpected state') } } Algebraic Data Types
  • 63. buzzwords… YAGNI DRY Stable Dependencies Principle Stable Abstractions Principle KISS MDA Monoids GRASP Code Generation Currying Continuations
  • 64. 4. Subsystems/Apps • Don’t reinvent the wheel:There is an app library for that! • Grab a good runtime library 
 (ramda, immutable.js, lodash-fp, etc, still not clear for TS thou) • Read more papers, e.g. 
 https://github.com/papers-we-love/papers-we-love • Use existing design patterns which address your problem • Use suitable data structures instead of arrays/objects • Use frameworks/libraries that fit your task
  • 66. Behavioral Complexity • Callbacks hell • PubSub aka Emitter hell • FRP comes to the rescue! • Event Streams (Signals/Observables) > Events • RxJS, Bacon.js, Kefir, Highland
  • 67. hoveredMarks = this.options.scrollContainer .map(scroll => scroll.getOrElseL(() => this.quill.root)) .switchMap(container => Observable.merge( Observable.fromEvent(container, 'mouseenter').mapTo(true), Observable.fromEvent(container, 'mouseleave').mapTo(false) ) ) .switchMap( inside => inside ? Observable.merge( this.options.contentUpdated.mapTo(None), this.options.scrollPositionChanged.mapTo(None), Observable.fromEvent<MouseEvent>(this.quill.root, 'mousemove') .auditTime(50) .map(e => { const node = document.elementFromPoint(e.clientX, e.clientY) const blot = Quill.find(node, true) as Blot return !blot || blot instanceof Quill ? None : this._getMarksByBlot(blot) }) ) : Observable.of(None).delay(200) ) .distinctUntilChanged(this._optionMarksEqual) .share() .startWith(None)
  • 68. Fin.
  • 72. Further reading 
 Articles on Requirements & Complexity • Programming complexity https://en.wikipedia.org/wiki/ Programming_complexity • Cyclomatic complexity https://en.wikipedia.org/wiki/ Cyclomatic_complexity • No Silver Bullet http://www.cs.nott.ac.uk/~pszcah/G51ISS/Documents/ NoSilverBullet.html • SOLID https://en.wikipedia.org/wiki/SOLID_(object-oriented_design) • The Coming Software Apocalypse https://www.theatlantic.com/ technology/archive/2017/09/saving-the-world-from-code/540393 • User story mapping https://www.scrumalliance.org/community/articles/ 2013/august/creating-an-agile-roadmap-using-story-mapping
  • 73. Further reading
 Useful papers, articles and tech • Papers we love 
 https://github.com/papers-we-love/papers-we-love • FP vs OOP 
 http://blog.cleancoder.com/uncle-bob/2014/11/24/ FPvsOO.html • AirBnb Sketch App 
 https://github.com/airbnb/react-sketchapp • FSM 
 https://en.wikipedia.org/wiki/Finite-state_machine
  • 74. Further reading
 Books and stuff • Code Complete • FRP https://www.manning.com/books/functional-reactive-programming • Refactoring: Improving the Design of Existing Code • UML Distilled: A Brief Guide to the Standard Object Modeling Language • Head First Design Patterns • Learning JavaScript Design Patterns • TypeScript Deep Dive https://www.gitbook.com/book/basarat/typescript/details • Functional JavaScript http://shop.oreilly.com/product/0636920028857.do • FP in Scala https://www.manning.com/books/functional-programming-in-scala • PureScript https://leanpub.com/purescript/read • Learn You a Haskell for Great Good http://learnyouahaskell.com