SlideShare a Scribd company logo
@mirocupak
The good, the bad, and the ugly
of Java API design
Miro Cupak
Co-founder & VP Engineering, DNAstack
October 31, 2019
@mirocupak 2
Features
• Collections API.
• Stack-walking API.
• Process API.
• HTTP client API.
@mirocupak
Collections API
3
@mirocupak 4
Best practices
• Take advantage of convenience factory methods for collections.
• Immutable collections via of/ofEntries and copies via copyOf.
• Less verbose, no static initializer blocks.
• Create immutable collections by default, only add mutability when needed.
• No need to worry about forgetting references to underlying collections.
• Thread-safe and can be shared freely (no need for defensive copies).
• Good performance.
• Prefer collecting into immutable collections using toUnmodifiableList,
toUnmodifiableSet, toUnmodifiableMap.
• Use toArray to convert collections to arrays.
@mirocupak 5
Antipatterns
• Obtaining collections through other data structures (Arrays.asList,
Stream.of).
• Pulling in external dependencies only to obtain immutable collections (e.g.
Guava and its Immutable*).
• Instance-initializer construct in an anonymous inner class to instantiate
collections.
• Performance over clean APIs ([List, Set, Map].of).
@mirocupak 6
Patterns
• Static factory methods to create objects (of/ofEntries/copyOf).
• Name concisely (convention: of).
• Concrete classes not as part of the public API with static methods on
interfaces returning instances (pattern for implementation flexibility).
• Static import when readability not jeopardized (java.util.Map.entry).
• Tuple wrapper objects and convenience methods to generate them when
multiple varargs needed (Map.ofEntries).
• Converting between types via copyOf.
• Constructor reference as a generating function (array in a toArray call).
• Immutability by default (collections with copies and collectors).
@mirocupak
Stack-walking API
7
@mirocupak 8
Best practices
• Take advantage of the Stream API to lazily access only certain elements.
• Be aware of StackWalker.Option.
• Don’t resolve classes manually.
• Use to show hidden and reflection frames.
@mirocupak 9
Antipatterns
• Using [Thread, Throwable].getStackTrace() to traverse selected
frames of the execution stack.
• Treating execution stack as text.
• Using strings to represent Class instances.
• Accessing things eagerly when only parts of them are needed.
• Surprising hidden method behaviour (omitting elements of the stack for
performance).
@mirocupak 10
Patterns
• Collections over arrays.
• Leveraging Stream API in API design.
• Choose suitable represetations (don’t model everything as strings).
• Good performance through lazy access via streams.
• Methods accepting functions on streams as parameters to maintain
consistent state and control (walk()).
• Obtaining configured instances via static factory methods parameterized
with enums (getInstance()).
• Work with a security manager (secure access to Class objects).
• Permission checks when constructing instead of using an object.
@mirocupak
Process API
11
@mirocupak 12
Best practices
• ProcessHandle is a clean way of obtaining information about processes.
• Take advantage of convenience methods: pid, info, command…
• Trigger actions on process termination via onExit.
• Connect ProcessBuilder with ProcessHandle via toHandle.
@mirocupak 13
Antipatterns
• Accessing process information via MXBeans or OS utilities.
• Pulling in external libraries for simple process management (e.g. Apache
Commons Exec).
• Incomplete APIs - providing functionality to start hard-to-manage resources
without providing the functionality to obtain information about them.
• APIs leading the clients to use non-portable constructs.
@mirocupak 14
Patterns
• Providing convenience methods for commonly used functionality.
• Compact fluent API to access nested information.
• Nested public interfaces to group and organize (ProcessHandle.Info).
• Using convenient static factory methods to obtain instances
(ProcessHandle.[current, of, allProcesses]).
• Returning streams instead of collections to streamline lazy processing of
many elements (allProcesses, children, descendants…).
• Returning CompletableFuture instances in asynchronous APIs
(onExit).
• Providing adapters via to* methods (toHandle).
@mirocupak
HTTP client API
15
@mirocupak 16
Best practices
• Clear organization: HttpClient, HttpRequest, HttpResponse.
• HttpURLConnection is not pleasant to use.
• The new client API is versatile, flexible and clean.
• Prefer functionality in the JDK to external libraries.
@mirocupak 17
Antipatterns
• Using HttpURLConnection directly.
• Inconsistent capitalization (HttpURLConnection).
• Overly abstract and general APIs (URLConnection).
• Unclear conceptual API model (URL).
• Type casting needed to obtain the right instance (openConnection).
• Using strings where methods or enums would be more practical
(setRequestMethod(“GET”)).
• Requiring the client to use I/O boilerplate (BufferedReader/
InputStreamReader/InputStream…).
@mirocupak 18
Antipatterns
• Mandatory blocking network I/O.
• Side effects and hidden assumptions (getInputStream).
• Inconsistent behaviour across APIs (URLConnection vs. Socket).
@mirocupak 19
Patterns
• Clear separation of concepts at the class level (HttpClient,
HttpRequest, HttpResponse).
• Builder.
• Asynchronous via CompletableFuture.
• Clear and consistent naming.
• Convenience methods to access commonly used features (statusCode,
body).
@mirocupak
Questions?
20

More Related Content

PDF
The good, the bad, and the ugly of Java API design
PDF
The good, the bad, and the ugly of Java API design
PDF
The good, the bad, and the ugly of Java API design
PDF
The Good, the Bad and the Ugly of Java API design
PDF
BigDataSpain 2016: Stream Processing Applications with Apache Apex
PPTX
Parallel Programming
PDF
ECMAScript 6 Overview & Comparision
PDF
Hibernate performance tuning
The good, the bad, and the ugly of Java API design
The good, the bad, and the ugly of Java API design
The good, the bad, and the ugly of Java API design
The Good, the Bad and the Ugly of Java API design
BigDataSpain 2016: Stream Processing Applications with Apache Apex
Parallel Programming
ECMAScript 6 Overview & Comparision
Hibernate performance tuning

What's hot (14)

PDF
Codeigniter Training Part2
PDF
Entity Framework Core 1.x/2.x Advanced
PDF
Reactive Streams
PPTX
What’s expected in Java 9
PPTX
What’s expected in Spring 5
PDF
Breathing new life into Apache Oozie with Apache Ambari Workflow Manager
PPTX
Multi-threading in the modern era: Vertx Akka and Quasar
PDF
New in Spring Framework 5.0: Functional Web Framework
PDF
Gradle - Build System
PDF
Training Slides: 303 - Replicating out of a Cluster
PPTX
FOSDEM19 MySQL Component Infrastructure
PPTX
Utilizing the OpenNTF Domino API
PPTX
ZZ BC#7 asp.net mvc practice and guideline by NineMvp
PDF
Creating Modular Test-Driven SPAs with Spring and AngularJS
Codeigniter Training Part2
Entity Framework Core 1.x/2.x Advanced
Reactive Streams
What’s expected in Java 9
What’s expected in Spring 5
Breathing new life into Apache Oozie with Apache Ambari Workflow Manager
Multi-threading in the modern era: Vertx Akka and Quasar
New in Spring Framework 5.0: Functional Web Framework
Gradle - Build System
Training Slides: 303 - Replicating out of a Cluster
FOSDEM19 MySQL Component Infrastructure
Utilizing the OpenNTF Domino API
ZZ BC#7 asp.net mvc practice and guideline by NineMvp
Creating Modular Test-Driven SPAs with Spring and AngularJS
Ad

Similar to The good, the bad, and the ugly of Java API design (20)

PPTX
Practices and Tools for Building Better APIs
PPT
How to design effective APIs
ODT
Designing Better API
PDF
Voxxed Athens 2018 - Clean Code with Java9+
PDF
Writing clean code with Java 9+
PPTX
How to define an api
PPTX
Golden Rules of API Design
PDF
Clean code with Java 9
PDF
Practices and tools for building better API (JFall 2013)
PDF
Practices and tools for building better APIs
PDF
Extracting Examples for API Usage Patterns
PPTX
How to build Sdk? Best practices
PPT
Api desgin
PDF
ApiDesign
PDF
API design
PDF
How to design good api
PDF
Training Semester Report, Api Types of Apps
PPTX
API-first development
PDF
How To Design A Good A P I And Why It Matters G O O G L E
PDF
OSGi Community Event 2010 - Dependencies, dependencies, dependencies
Practices and Tools for Building Better APIs
How to design effective APIs
Designing Better API
Voxxed Athens 2018 - Clean Code with Java9+
Writing clean code with Java 9+
How to define an api
Golden Rules of API Design
Clean code with Java 9
Practices and tools for building better API (JFall 2013)
Practices and tools for building better APIs
Extracting Examples for API Usage Patterns
How to build Sdk? Best practices
Api desgin
ApiDesign
API design
How to design good api
Training Semester Report, Api Types of Apps
API-first development
How To Design A Good A P I And Why It Matters G O O G L E
OSGi Community Event 2010 - Dependencies, dependencies, dependencies
Ad

More from Miro Cupak (20)

PDF
Exploring the latest and greatest from Java 14
PDF
Exploring reactive programming in Java
PDF
Exploring the last year of Java
PDF
Local variable type inference - Will it compile?
PDF
Local variable type inference - Will it compile?
PDF
Exploring reactive programming in Java
PDF
Master class in modern Java
PDF
Exploring reactive programming in Java
PDF
Writing clean code with modern Java
PDF
Master class in modern Java
PDF
Exploring reactive programming in Java
PDF
Writing clean code with modern Java
PDF
Exploring what's new in Java 10 and 11 (and 12)
PDF
Exploring what's new in Java 10 and 11
PDF
Exploring what's new in Java in 2018
PDF
Reactive programming in Java
PDF
Master class in Java in 2018
PDF
Exploring reactive programming with Java
PDF
Exploring reactive programming in Java
PDF
Writing clean code with Java in 2018
Exploring the latest and greatest from Java 14
Exploring reactive programming in Java
Exploring the last year of Java
Local variable type inference - Will it compile?
Local variable type inference - Will it compile?
Exploring reactive programming in Java
Master class in modern Java
Exploring reactive programming in Java
Writing clean code with modern Java
Master class in modern Java
Exploring reactive programming in Java
Writing clean code with modern Java
Exploring what's new in Java 10 and 11 (and 12)
Exploring what's new in Java 10 and 11
Exploring what's new in Java in 2018
Reactive programming in Java
Master class in Java in 2018
Exploring reactive programming with Java
Exploring reactive programming in Java
Writing clean code with Java in 2018

Recently uploaded (20)

PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
AI in Product Development-omnex systems
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
ai tools demonstartion for schools and inter college
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
System and Network Administration Chapter 2
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Softaken Excel to vCard Converter Software.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Operating system designcfffgfgggggggvggggggggg
Design an Analysis of Algorithms II-SECS-1021-03
Which alternative to Crystal Reports is best for small or large businesses.pdf
AI in Product Development-omnex systems
CHAPTER 2 - PM Management and IT Context
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
ai tools demonstartion for schools and inter college
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Upgrade and Innovation Strategies for SAP ERP Customers
System and Network Administration Chapter 2
How to Migrate SBCGlobal Email to Yahoo Easily
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free

The good, the bad, and the ugly of Java API design

  • 1. @mirocupak The good, the bad, and the ugly of Java API design Miro Cupak Co-founder & VP Engineering, DNAstack October 31, 2019
  • 2. @mirocupak 2 Features • Collections API. • Stack-walking API. • Process API. • HTTP client API.
  • 4. @mirocupak 4 Best practices • Take advantage of convenience factory methods for collections. • Immutable collections via of/ofEntries and copies via copyOf. • Less verbose, no static initializer blocks. • Create immutable collections by default, only add mutability when needed. • No need to worry about forgetting references to underlying collections. • Thread-safe and can be shared freely (no need for defensive copies). • Good performance. • Prefer collecting into immutable collections using toUnmodifiableList, toUnmodifiableSet, toUnmodifiableMap. • Use toArray to convert collections to arrays.
  • 5. @mirocupak 5 Antipatterns • Obtaining collections through other data structures (Arrays.asList, Stream.of). • Pulling in external dependencies only to obtain immutable collections (e.g. Guava and its Immutable*). • Instance-initializer construct in an anonymous inner class to instantiate collections. • Performance over clean APIs ([List, Set, Map].of).
  • 6. @mirocupak 6 Patterns • Static factory methods to create objects (of/ofEntries/copyOf). • Name concisely (convention: of). • Concrete classes not as part of the public API with static methods on interfaces returning instances (pattern for implementation flexibility). • Static import when readability not jeopardized (java.util.Map.entry). • Tuple wrapper objects and convenience methods to generate them when multiple varargs needed (Map.ofEntries). • Converting between types via copyOf. • Constructor reference as a generating function (array in a toArray call). • Immutability by default (collections with copies and collectors).
  • 8. @mirocupak 8 Best practices • Take advantage of the Stream API to lazily access only certain elements. • Be aware of StackWalker.Option. • Don’t resolve classes manually. • Use to show hidden and reflection frames.
  • 9. @mirocupak 9 Antipatterns • Using [Thread, Throwable].getStackTrace() to traverse selected frames of the execution stack. • Treating execution stack as text. • Using strings to represent Class instances. • Accessing things eagerly when only parts of them are needed. • Surprising hidden method behaviour (omitting elements of the stack for performance).
  • 10. @mirocupak 10 Patterns • Collections over arrays. • Leveraging Stream API in API design. • Choose suitable represetations (don’t model everything as strings). • Good performance through lazy access via streams. • Methods accepting functions on streams as parameters to maintain consistent state and control (walk()). • Obtaining configured instances via static factory methods parameterized with enums (getInstance()). • Work with a security manager (secure access to Class objects). • Permission checks when constructing instead of using an object.
  • 12. @mirocupak 12 Best practices • ProcessHandle is a clean way of obtaining information about processes. • Take advantage of convenience methods: pid, info, command… • Trigger actions on process termination via onExit. • Connect ProcessBuilder with ProcessHandle via toHandle.
  • 13. @mirocupak 13 Antipatterns • Accessing process information via MXBeans or OS utilities. • Pulling in external libraries for simple process management (e.g. Apache Commons Exec). • Incomplete APIs - providing functionality to start hard-to-manage resources without providing the functionality to obtain information about them. • APIs leading the clients to use non-portable constructs.
  • 14. @mirocupak 14 Patterns • Providing convenience methods for commonly used functionality. • Compact fluent API to access nested information. • Nested public interfaces to group and organize (ProcessHandle.Info). • Using convenient static factory methods to obtain instances (ProcessHandle.[current, of, allProcesses]). • Returning streams instead of collections to streamline lazy processing of many elements (allProcesses, children, descendants…). • Returning CompletableFuture instances in asynchronous APIs (onExit). • Providing adapters via to* methods (toHandle).
  • 16. @mirocupak 16 Best practices • Clear organization: HttpClient, HttpRequest, HttpResponse. • HttpURLConnection is not pleasant to use. • The new client API is versatile, flexible and clean. • Prefer functionality in the JDK to external libraries.
  • 17. @mirocupak 17 Antipatterns • Using HttpURLConnection directly. • Inconsistent capitalization (HttpURLConnection). • Overly abstract and general APIs (URLConnection). • Unclear conceptual API model (URL). • Type casting needed to obtain the right instance (openConnection). • Using strings where methods or enums would be more practical (setRequestMethod(“GET”)). • Requiring the client to use I/O boilerplate (BufferedReader/ InputStreamReader/InputStream…).
  • 18. @mirocupak 18 Antipatterns • Mandatory blocking network I/O. • Side effects and hidden assumptions (getInputStream). • Inconsistent behaviour across APIs (URLConnection vs. Socket).
  • 19. @mirocupak 19 Patterns • Clear separation of concepts at the class level (HttpClient, HttpRequest, HttpResponse). • Builder. • Asynchronous via CompletableFuture. • Clear and consistent naming. • Convenience methods to access commonly used features (statusCode, body).