Enterprise AI Trend Report: Gain insights on ethical AI, MLOps, generative AI, large language models, and much more.
2024 Cloud survey: Share your insights on microservices, containers, K8s, CI/CD, and DevOps (+ enter a $750 raffle!) for our Trend Reports.
Software Engineer at IBM
Saddle Brook, US
Joined May 2013
I am devoted to continuously learning and improving as a software developer and sharing my experience with others in order to improve their expertise. I am also dedicated to personal and professional growth through diligent studying, discipline, and meaningful professional relationships. When not writing, I can be found playing hockey, practicing Brazilian Jiu-jitsu, watching the NJ Devils, reading, writing, or drawing. ~II Timothy 1:7~ Twitter: @justinmalbano
Embry-Riddle Aeronautical University · Software Engineering
Master's, Bachelor's
Sep 2010 - May 2015
Stats
Reputation: | 10031 |
Pageviews: | 3.8M |
Articles: | 50 |
Comments: | 172 |
Software Supply Chain Security
Design Patterns
Cloud-Based Automated Testing Essentials
Getting Started With GitHub Actions
JavaScript Test Automation Frameworks
End-to-End Testing Automation Essentials
Automated Testing at Scale
Node.js
The Modern DevOps Lifecycle
While DevOps is here to stay, as the years pass, we must continuously assess and seek improvements to our existing software processes, systems, and culture — and DevOps is no exception to that rule. With business needs and customer demands constantly shifting, so must our technology, mindsets, and architecture in order to keep pace.Now is the time for this movement that's all about "shifting left" to essentially shift.In our annual DevOps Trend Report, we explore both its fundamental principles as well as the emerging topics, methodologies, and challenges surrounding the engineering ecosystem. Within our "Key Research Findings" and featured articles from our expert community members, readers will find information on core DevOps topics as well as new insights on what's next for DevOps in 2024 and beyond. Join us to learn about the state of CI/CD pipelines, the impact of technical debt, patterns for supply chain management<>DevOps, the rise of platform engineering, and even more!
DevOps
The DevOps movement has paved the way for CI/CD and streamlined application delivery and release orchestration. These nuanced methodologies have not only increased the scale and speed at which we release software, but also redistributed responsibilities onto the developer and led to innovation and automation throughout the SDLC.DZone's 2023 DevOps: CI/CD, Application Delivery, and Release Orchestration Trend Report explores these derivatives of DevOps by diving into how AIOps and MLOps practices affect CI/CD, the proper way to build an effective CI/CD pipeline, strategies for source code management and branching for GitOps and CI/CD, and more. Our research builds on previous years with its focus on the challenges of CI/CD, a responsibility assessment, and the impact of release strategies, to name a few. The goal of this Trend Report is to provide developers with the information they need to further innovate on their integration and delivery pipelines.
Enterprise Application Security
Data breaches, ransomware attacks, and other security vulnerabilities have become the norm in recent years. Hackers have become shrewder. And with that, development teams bear the responsibility of ensuring that all stages of the SDLC have strong security.DZone's 2022 Trend Report, Enterprise Application Security: Building Secure and Resilient Applications, focuses on key factors of security practices including supply chain security, principles of zero-trust security, how to secure mobile applications, common DevSecOps practices, and what to do after your organization experiences a security breach. Our research dives into sentiments on perceived application security risks, development techniques for securing applications, and where the role of security lies for teams within today's organizational structures. The goal of this Trend Report is to equip developers with the tools, best practices, and advice they need to help implement security at every stage of the SDLC.
Low Code and No Code
As the adoption of no-code and low-code development solutions continues to grow, there comes many questions of its benefits, flexibility, and overall organizational role. Through the myriad of questions, there is one main theme in the benefit of its use: leveraging no-code and low-code practices for automation and speed to release.But what are the pain points that these solutions seek to address? What are the expected vs. realized benefits of adopting a no- or low-code solution? What are the current gaps that these solutions leave in development practices? This Trend Report provides expert perspectives to answer these questions. We present a historical perspective on no and low code, offer advice on how to migrate legacy applications to low code, dive into the challenges of securing no- and low-code environments, share insights into no- and low-code testing, discuss how low code is playing a major role in the democratization of software development, and more.
DevOps
With the need for companies to deliver capabilities faster, it has become increasingly clear that DevOps is a practice that many enterprises must adopt (if they haven’t already). A strong CI/CD pipeline leads to a smoother release process, and a smoother release process decreases time to market.In DZone’s DevOps: CI/CD and Application Release Orchestration Trend Report, we provide insight into how CI/CD has revolutionized automated testing, offer advice on why an SRE is important to CI/CD, explore the differences between managed and self-hosted CI/CD, and much more. The goal of this Trend Report is to offer guidance to our global audience of DevOps Engineers, Automation Architects, and all those in between on how to best adopt DevOps practices to help scale the productivity of their teams.
Low-Code Development
Development speed, engineering capacity, and technical skills are among the most prevalent bottlenecks for teams tasked with modernizing legacy codebases and innovating new solutions. In response, an explosion of “low-code” solutions has promised to mitigate such challenges by abstracting software development to a high-level visual or scripting language used to build integrations, automate processes, construct UI, and more. While many tools aim to democratize development by reducing the required skills, others seek to enhance developer productivity by eliminating needs such as custom code for boilerplate app components. Over the last decade, the concept of low code has matured into a category of viable solutions that are expected to be incorporated within mainstream application development. In this Trend Report, DZone examines advances in the low-code space, including developers' perceptions of low-code solutions, various use cases and adoption trends, and strategies for successful integration of these tools into existing development processes.
CI/CD
In 2020, DevOps became more crucial than ever as companies moved to distributed work and accelerated their push toward cloud-native and hybrid infrastructures. In this Trend Report, we will examine what this acceleration looked like for development teams across the globe, and dive deeper into the latest DevOps practices that are advancing continuous integration, continuous delivery, and release automation.
Modern Web Development
The web is evolving fast, and developers are quick to adopt new tools and technologies. DZone’s recent 2021 Modern Web Development survey served to help better understand how developers build successful web applications, with a focus on how decisions are made about where computation and storage should occur.This Trend Report will help readers examine the pros and cons of critical web development design choices, explore the latest development tools and technologies, and learn what it takes to build a modern, performant, and scalable web application. Readers will also find contributor insights written by DZone community members, who cover topics ranging from web performance optimization and testing to a comparison of JavaScript frameworks.Read on to learn more!
API Design and Management
Discover what you need to know about the state of API design and management. This report explores a wide range of topics from REST API discovery and navigation to common integration pain points and how developers are thinking about APIs.This report covers in-depth original research on developer preferences surrounding API programs and integrated systems. Additionally, experts in the field share their perspectives on effective API design as well as secure API strategies and best practices.
JavaScript Frameworks
JavaScript is constantly at the top of developer surveys. With the rise of Single Page Applications and front-end frameworks, and the onslaught of languages that now compile into JS, it's easy to see that JavaScript will continue to play a pivotal role in front-end and back-end development for the foreseeable future. What that future looks like exactly is in flux, especially as it relates to which frameworks are in vogue and which are on their way out. DZone’s JavaScript Frameworks Trend Report provides the perspectives of industry professionals and leaders, detailing the latest news and trends concerning JavaScript frameworks, all with the hope of giving readers a better understanding of which of these frameworks is right for their specific development needs.
Application Security
DZone Trend Reports will expand on the content from DZone Research Guides that our readers have told us is most useful. The Application Security Trend Report analyzes new developments in the increasingly important field of AppSec to predict what's next.
Comments
Feb 09, 2022 · Justin Albano
Thank you!
Nov 20, 2021 · Justin Albano
Glad this was able to help you. Thank you for the feedback.
Jul 29, 2021 · Justin Albano
That's an awesome tip I wasn't aware of! That makes life a lot easier. I've updated the article with that information and credited you with that tip and cited the source you mentioned. Thank you again, that's a great tip.
Jul 29, 2021 · Justin Albano
Thank you for the heads up. I appreciate you taking the time to make the correction. System.in is an InputStream, not a PrintStream, so you are correct that it does not have a format() method. I've updated the article to reflect that.
Jul 23, 2021 · Justin Albano
Thank you, and thanks for taking the time to read and comment.
Jul 22, 2021 · Justin Albano
Thank you, and thank you for taking the time to read and comment.
Jul 22, 2021 · Justin Albano
Thank you. I appreciate you taking the time to read it and comment.
May 20, 2021 · Melissa Habit
Thanks for taking the time you provide your thoughts, Robert. I really appreciate it.
All of the points you bring up are very good points. Generally, when I refer to the "customer" in this article, it's not the customer of our product per-say, it's the person or software written by a person that consumes the API.
In perfect software style, the answer to your question of who decides to use the API is: It depends. Sometimes it's the developer who gets to decide, sometimes it's a business person (or persons), and sometimes it's both. In the case of the developer, sometimes we're asked to decide on an API that works best to solve the problem (or never asked at all, we just find the one we think works best). Sometimes it's a business person who wants to build a relationship with a company, so they agree to use their API without much knowledge of how well that API is written. In a lot of cases, it's some combination of these scenarios.
The design principles listed in this article are intended for the development side of the decision, but they also aid in the business side as well (i.e., if the API is easy to consume, this will likely lead to a less-expensive implementation cost on the part of the consumer).
Dec 08, 2020 · Justin Albano
Thank you! I really appreciate it!
Aug 10, 2020 · Justin Albano
Thank you, Dilek! I appreciate the feedback
Aug 04, 2020 · Justin Albano
I appreciate taking the time to provide your feedback and catching those typos. They have been corrected. Thank you.
Jun 26, 2020 · Justin Albano
You're welcome! Thanks for the feedback
Jun 16, 2020 · Justin Albano
First, I appreciate your feedback.
I agree. Non-reified types and nullity are two of the larger difficulties to work around in Java. This article, though, is intended to explain how to use Java as it is. While I hope improvements (even if they will leave old Java versions behind) are made, I am hoping to help those who are programming in Java as it is today.
Although I do agree that Optional does introduce some overhead (mentioned in the Alternatives section), in many cases, it's minimal. As stated, only when used in large scale or in performance-critical sections does Optional seriously impact performance.
Again, thank you for your feedback. I appreciate you taking the time to comment.
Apr 29, 2020 · Justin Albano
You are correct. Thank you for catching that mistake (it has now been corrected). I appreciate your feedback (and your sharp eye).
Apr 28, 2020 · Justin Albano
You're welcome. I'm very glad it was useful for you. Thanks for the feedback!
Jan 25, 2020 · Gaurav Kukade
Great article and great explanation.
One more thing to consider are null values. I.e., when comparing a String variable (str) to a known String, oftentimes it will be written as "foo".equals(str) rather than str.equals("foo") since there is a possibility that str may be null (and calling equals() would through an NPE).
Another way to solve this is by using the Objects.equals method: Objects.equals(str, "foo"). This method will return true if both arguments are null, though, so that logic may not be applicable in all scenarios.
Jan 09, 2020 · Justin Albano
Dec 03, 2019 · Lauren Forbes
From experience on a microservices HATEOAS project, one way is to provide URLs that route through the gateway. For example, instead of http://localhost:8080/users, we would use https://mygateway.com/users, where users/ is a route known by the gateway. Maybe the gateway has load-balancing or directly routes to a single microservice, but those are internal details that are abstracted.
In general, the idea is to always use externally-addressable links that hide the details of the gateway (and even hide that a gateway is in use). The details are too nuanced for a single comment, but that's the basic approach we used (not perfect and it has its downsides).
Oct 30, 2019 · Justin Albano
Thanks, Dieter. I appreciate your feedback.
Sep 04, 2019 · Justin Albano
Thank you. I appreciate the feedback.
Jul 11, 2019 · Justin Albano
For the case of brevity, I did not include Spring Boot and auto-configuration annotations in this article, but I may do a follow-up article that includes these topics (these concepts can leverage the concepts explained in this article).
Thank you for the suggestion and I appreciate your feedback!
Jul 02, 2019 · Justin Albano
Definitely right. For this article, I tried to keep it to the most common ones, but I may write a follow-up article and include more annotations, such as @RestController. I will definitely keep your suggestion in mind. Thanks!
Apr 24, 2019 · Justin Albano
Thank you! I'm glad you enjoyed it!
Apr 14, 2019 · Justin Albano
Thank you! Glad you enjoyed it.
Apr 11, 2019 · Justin Albano
Thank you! I appreciate the feedback.
Apr 11, 2019 · Justin Albano
Thanks for the feedback. And you are correct: I made a static import when creating the example, but when I posted it, I forgot to add the class name back in.
Thanks for find that. It has been corrected.
Dec 24, 2018 · Justin Albano
Thanks for the feedback, Michael. I'm glad it helped!
Dec 07, 2018 · Justin Albano
Thanks. I appreciate the feedback.
Nov 25, 2018 · Justin Albano
Thank you! I appreciate your feedback.
Sep 17, 2018 · Justin Albano
A full description of the proposed bytecode changes can be found in The State of the Values article.
Sep 14, 2018 · Justin Albano
A link to the source code for this article has now been added to the introduction and can be found here: https://github.com/albanoj2/dzone-intro-json-with-java
Sep 14, 2018 · Justin Albano
I appreciate the feedback. You're right, it's good to have full, complete examples. I will attach a completed set of examples (based on the snippets in the article) as soon as possible. Thank you again for the feedback.
Sep 14, 2018 · Justin Albano
Thanks. I appreciate the feedback and I'm glad the article could help.
Aug 02, 2018 · Justin Albano
I'm glad you enjoyed it. Thanks for the feedback!
Jul 25, 2018 · Justin Albano
Thanks for the feedback. I will definitely consider creating an article on heap dumps in the future.
Jul 23, 2018 · Justin Albano
For most applications, the memory and allocation overhead is likely negligible, especially since the created empty list contains zero elements. If this becomes a performance bottleneck (after some performance profiling) or if the application is extremely performant in terms of memory, returning null would be an acceptable technique.
Basically, in a large majority of cases, returning an empty list is logically more consistent, but if high performance is required, nulls can still be used.
Thank you for taking the time to comment.
Jul 14, 2018 · Justin Albano
Thanks for the feedback. I appreciate you taking the time to comment and thank you for catching those typos. They have been corrected.
Jun 26, 2018 · Justin Albano
Thank you. I appreciate you taking the time to provide feedback.
Jun 07, 2018 · Justin Albano
Glad it helped and glad you were able to get your first annotation working
Apr 22, 2018 · Justin Albano
Glad you enjoyed it. Thank you for the feedback.
Apr 21, 2018 · Justin Albano
Good catch. Uses of updateAnimalAdded have been changed to onAnimalAdded for consistency. Thank you for the feedback.
Apr 09, 2018 · Robin Rizvi
Great article: Really comprehensive. Also, kudos on the clever title.
Apr 03, 2018 · Justin Albano
Duly noted. (Although, there are two types of PaymentMethodFactory objects in this article: One for selecting a payment method through reflection and another for selecting one through a configuration file.)
Apr 01, 2018 · Justin Albano
What topics or details would you like to see so that I can include them in future articles and better incorporate your criticism? Again, I appreciate you taking the time to reach out and provide your feedback.
Mar 30, 2018 · Justin Albano
Providing dynamic parameters can be complex, depending on how you decide to do did. For example, using OSGi, using some external service, etc. Within the context of the Strategy Pattern, so long as the dynamic parameters can be provided, a new payment method (such as credit card) can either be instantiated manually (either using the new keyword or through a factory method) or through reflection, as described in this article.
Mar 29, 2018 · Justin Albano
Thank you for the feedback. To answer your question better, what you do specifically mean by "dynamic parameters?"
Mar 28, 2018 · Justin Albano
Glad you enjoyed the article.
Truth be told, these 5 points on not really "secrets" since they are only "hidden" in plain sight in the Java Language Specification, but they were just 5 topics that I came across in the last few weeks that I had not known before and had not seen other articles or books spend much time on them. I'm sure they will be known to others, but I had personally never seen some of these points before.
Mar 28, 2018 · Justin Albano
Very true. I've updated the listings to use capital L to make it more obvious that the literals are longs.
Mar 28, 2018 · Justin Albano
Strictly speaking, no. There are right there in the JLS for anyone to see (if they so choose to read it), but many of them are not used on a daily basis, and just anecdotally, many developers do not know they exist (myself included until recently).
Mar 26, 2018 · Jordan Baker
It is difficult to tell what the setter is doing just by inspection. In general, boolean arguments for any method (even more so with other arguments besides the boolean flag) can be difficult to read. For example, setComplete(true) is less intelligible than markComplete() (since we have to think about what true or false means and how that will effect the call), or in a case with more arguments, setOrderStatus(someStatus, true), it is difficult to tell what the boolean means. In essence, it is hard to grasp the meaning of the call just from the call itself.
I appreciate you taking the time to ask this and I appreciate you working through this series of articles.
Mar 15, 2018 · Justin Albano
How so?
Mar 14, 2018 · Justin Albano
Thank you. Glad you enjoyed it.
Mar 14, 2018 · Justin Albano
Thank you for finding that typo. It has been corrected.
Mar 14, 2018 · Justin Albano
Thank you. Glad you enjoyed it.
Mar 14, 2018 · Justin Albano
Thank you, Denis. I appreciate your feedback and I'm glad you enjoyed the article.
Mar 09, 2018 · Justin Albano
Glad you enjoyed it and thanks for the feedback.
Mar 09, 2018 · Justin Albano
Glad you enjoyed it and it was helpful for you. Thanks for the feedback. There are also more parts to this series:
- The Developer's Guide to Collections: Lists
- The Developer's Guide to Collections: Sets
- The Developer's Guide to Collections: Queues
Mar 07, 2018 · Justin Albano
The requireNonNullElse method was added in JDK 9. I updated the article to explicitly mention that this method was not added until JDK 9. Unfortunately, I didn't originally make a distinction between the requireNonNull method (which was added in JDK 7) and the requireNonNullElse method (which was added in JDK 9). Thanks for taking the time to bring up this issue. I appreciate it.
Mar 07, 2018 · Justin Albano
I'm glad you enjoyed the article. Thanks for catching those two mistakes: They have been corrected.
Mar 05, 2018 · Justin Albano
Thank you. I'm glad you enjoyed it.
Mar 03, 2018 · Justin Albano
Thank you for the feedback.
Mar 02, 2018 · Justin Albano
Looking back on it, you are correct. What I really meant to say was that C# classes have non-virtual methods by default. You are correct: That is not the same as saying the class is final (or non-overridable). I revised the article and took out the statement about C# since it would require too much explanation and would detract from the intent of the article.
Thanks for catching that and that's not nit-picking in my book: You are correct about that misstatement in the article and I'm glad you took the time to give me constructive criticism.
Mar 02, 2018 · Justin Albano
You are correct. Thank you for catching that typo and thank you for your feedback.
Mar 01, 2018 · Justin Albano
You are correct, that was a typo. I had created the copy static method for Transmission but accidentally did not use it in the constructor for Car. That snippet has been updated. Thank you for finding that error.
Feb 28, 2018 · Justin Albano
That is very true in a lot of cases. The case that Josh Bloch uses is that of a Point object and CountedPoint object, where the counted point simply increments a static counter variable. In that case, Point(0, 1) and CountedPointer(0, 1) both represent the same Cartesian location, but do not collide in the same manner as a matching Car and Dog with different names. Just wanted to include this to make the example that Bloch gives explicit.
Feb 28, 2018 · Justin Albano
I agree, although a obj.getClass() != getClass() style comparison does have the side-effect seen in the set example above.
(For the record, this is only an issue if providing a custom equals method implementation. If no such override is warranted, and the default implementation (obj == this) suffices, it should be used. It avoids a great deal of the confusion of extra-linguistic documentation.)
Feb 28, 2018 · Justin Albano
You are correct that there is a violation of symmetry here, but it is a very specific violation: Creating a subclass with a new field not present in the superclass. If the subclass does not add new fields and require the equals method to be overridden (or explicitly overrides the equals method), no issue occurs (Gist found here).
In that case, there is no issue, but if we add a new field, we introduce an issue (Gist found here):
The trade-off is that if we do not use instanceof and allow for subclasses to match superclasses (upholding the Liskov Substitution Principle), then Java frameworks that use the equals method will break. For example, if we use the first equals, where Bar does not add any fields and uses the equals method implementation from the Foo class, the following does not work as expected (Gist found here).
Notice that the Bar class does not behave in the same manner as the Foo class (it is allowed to be added to the Set even though an identical Foo object was rejected), thus violating the Liskov Substitution Principle. I do not do this discussion justice in this comment, but Josh Bloch provides a much better description of this problem in Item 10 of Effective Java, 3rd Edition. His suggestion is the following:
Unfortunately, the symmetry rule is not as clear-cut as it should be due to competing interests. There is a trade-off to be had here between satisfying the Liskov Substitution Principle and upholding strict equals symmetry with subclasses with new fields.
Feb 26, 2018 · Justin Albano
This is very wise advice
Feb 26, 2018 · Justin Albano
Correct. I should have made a distinction (the Arrays.asList uses the private inner class ArrayList).
Feb 25, 2018 · Justin Albano
I think there may be a misunderstanding here. In the particular instance that you quote, I refer to the of static methods included in the List and Map interfaces, both of which were added in Java 9, as denoted by the @since JavaDoc annotation in each of these methods (see the List documentation). This does not preclude or refer to any implementations of a simplified list creation method present in Java, of which, many have existed before JDK 9, as you rightly noted.
There have existed methods such as Arrays.asList for many years (or the ArrayList constructor itself), but this method differs in many important ways from the List.of method. In particular, the contract for this method is different in that it always creates a mutable List backed by the supplied array. As a matter of fact, it returns an ArrayList, using the ArrayList constructor that accepts a variable number of arguments:
It's intended purpose is not to create lists, but rather, bridge the gap between arrays and their Collection counterparts (such as List). In contrast, the List.of method returns an immutable List that contains the supplied elements. It also has multiple overloadings to ensure that in most cases (of less than 10 elements), an intermediate array is not created to store the variable number of arguments:
In writing these articles, I do my best to be diligent, precise, and well-researched. As seen from the constructive comments by many astute readers, I make mistakes and many of the readers are kind enough to bring them to my attention, and critically correct them. If there is some error in my article, I am glad to discuss it and learn from any reader, for they have a lot to teach me and I do my best to learn from them.
Feb 23, 2018 · Justin Albano
I agree in many cases, but it depends on the context. Addressing the quote: That quote does not mean only use one or the other or that FP and traditional programming are mutually exclusive. They can be mixed and matched. I.e. if a for loop is easier to read, use it. If a lambda makes it easier, use it. Even if those usages are 2 lines apart.
Feb 23, 2018 · Justin Albano
Thank you for that optimization (you are correct: The Iterable interface includes the forEach method). Although it does reduce the clutter, the reliability issue with the nested iteration still holds.
Feb 23, 2018 · Justin Albano
That method is just a stub for demonstration purposes so it does not have a stated implementation. Many times, lower-level methods (such as those used by databases or over-the-wire protocols) will return null to denote that something is not available. If an error occurred, they would throw an exception, but in many cases, these methods do not consider "no data" an error.
Feb 23, 2018 · Justin Albano
Well-written will be subjective, but it's worth it to browse through some of the following:
- Spring
- JUnit
- Apache Kafka
Again, well-written is subjective, but there's a lot that can be gained by looking at code written to solve monumental problems (such as Spring or many of the Apache projects).
Feb 23, 2018 · Justin Albano
Thank you for the feedback. Glad you enjoyed it.
Feb 23, 2018 · Justin Albano
Thanks for catching that. That was a typo and it has been fixed.
Feb 23, 2018 · Justin Albano
Either one would work. Personally, I find it more readable to include the else, but that's just a personal preference. You could also remove the braces for both if statements and it would work as well:
public boolean equals(Object o){
if (o==this) return true;
if (!(o instanceof Exam)) return false;
...
Feb 23, 2018 · Justin Albano
Be sure to include two braces. I.e., ArrayList<>() {{ /*...*/ }; Also, depending on which version of JDK you are using, the compiler may not be able to infer the type of the generic argument for the ArrayList. Thus, using the diamond operator ("<>") may cause the error you see. The source code in this article was written using JDK 9.
Feb 23, 2018 · Justin Albano
I agree and your points are well taken. From personal experience, along with the opinion of others I've seen, Scala can be difficult to pick up because it does so many thing (well). The volume of learning can at first be a big hurdle to surmount. I agree that it has great benefits, but it does take a lot of work (in terms of learning) to become proficient.
Feb 22, 2018 · Justin Albano
From what I can tell, the reason that the requireNonNull method was created was not necessary to reduce the number of explicitly thrown exceptions, but because the method returns the supplied object if it is not null. That allows the null check and assignment to be shrunk to one line. More of convenience than to remove explicit throw statements. That's my understanding: I would have to look at what the JDK developers said to get a better idea of why they did it.
Personally, I try to do whatever is the most readable. If explicitly throwing an exception works, then I'll use it. If it reads better to have a method that throws the exception, then I'll go with that. I apologize for not giving a very objective answer, but I just try to make a judgment call depending on the context.
Feb 22, 2018 · Justin Albano
That was a typo. Thanks for the catch. The constructor should have a Transmission parameter.
Feb 22, 2018 · Justin Albano
I agree with you both that Scala is a very good language, but just telling people to migrate is not a very good way to win fans. In a production environment with tight deadlines and reliance on Java, it may not be practical, or at least just yet. Learning Scala is not trivial. In order for people to latch on, Scala advocates have to meet developers where they are at in a practical way.
Feb 22, 2018 · Justin Albano
Thanks for the feedback. It is a quirky trick, but I wouldn't suggest it in practice.
Feb 22, 2018 · Justin Albano
Glad you enjoyed it. Thanks for taking the time to provide feedback and ask questions.
Feb 21, 2018 · Justin Albano
Completely agree. Especially with the new List.of and Map.of methods, the syntactic appeal of double-bracing becomes almost non-existent.
Feb 21, 2018 · Justin Albano
Glad you enjoyed the article.
In this case, I made the copy() method static because it represents a named constructor. I could have also made it an instance method. This was more of a personal choice, since the method involved the creation of a new object (closely associated with construction/instantiation). Either one would have worked and in some cases, the instance method may be better.
Feb 21, 2018 · Justin Albano
Thanks, Denis. I'm glad you enjoyed it.
Feb 21, 2018 · Justin Albano
I definitely agree. Learning a JVM language beyond Java is a great way to become a better Java programmer. I would even go one step further and say that learning a (or more than one) non-JVM language. Each has its own quirks and "culture" and learning these helps to break out of the box of "we do it this way because that's the way we've always done it."
Feb 21, 2018 · Justin Albano
Thanks for the feedback. And you are correct. I over-generalized on that statement.
Feb 20, 2018 · Justin Albano
I can understand your point. Total ordering a bit more general, since it can be accomplished using either a Comparator or through natural ordering. I may not have been as explicit as I should have. Merging your idea with the suggestions in the article, the suggestion in the article could be rephrased the suggestion to: Use TreeSet when a Comparator or natural ordering is needed (either of which constitutes total ordering).
Feb 19, 2018 · Justin Albano
These are both very good options. I tried to keep this article focused on techniques that are within the language itself, but if a team is all using the same IDE, both of the annotations-based techniques you described are good options.
Feb 19, 2018 · Justin Albano
Thank you. I'm glad you enjoyed it.
Feb 18, 2018 · Justin Albano
Okay, that part I understand. You're right. Since the removeIf method does an in-place modification, it is not side-effect free. Many of the methods of the Collection interface (removeIf being one of them) have side-effects because it is assumed the collection is mutable. If collections were immutable, they could be made side-effect free, but that would also be very inefficient (i.e. a new collection is made every time new items are added). For that decision, I'd have to defer to the JDK team. That's a decision they made for better or worse.
In either case, I appreciate you're constructive criticism.
Feb 18, 2018 · Justin Albano
Thanks for the feedback. To my understanding, the item in Effective Java is centered around using "side-effect free functions." In that respect, so long as the Predicate for removeIf does not have side-effects, it follows this item. In what respect do you see the removeIf example breaking the side-effect free item? (This is a sincere question so I can understand where you are coming from.)
Feb 18, 2018 · Justin Albano
Thank you, Denis. I'm glad you enjoyed it. Thank you for the feedback.
Feb 17, 2018 · Justin Albano
It matters what context the language is used in. Some think C++ is too expressive or too verbose (I.e. The Rule of 3 and manual memory management), but if you're putting a military aircraft into flight, that may be what you need.
I agree with you that Java is far from a perfect language, but being supremacist about any language is an unwise decision.
Feb 17, 2018 · Justin Albano
Thanks for the feedback. The public final fields are actually typos and should be private final. Thanks for catching that. Those typos have been corrected in both the article and the accompanying Github repository.
Feb 16, 2018 · Justin Albano
Although Scala does have many benefits over Java, a list of 3 things not to do in Scala can be created just as easily. Every language has its trade-offs.
Feb 16, 2018 · Justin Albano
I agree. Having a getter or setter should give pause. In some cases, there may be good reasons to have one or the other, or both, but in most cases, they are unneeded. It should not be the default to include them.
Feb 16, 2018 · Justin Albano
Although I agree that there are some great benefits to other JVM languages, there are also some disadvantages as well. While a lot of these problems are solved with languages such as Kotlin, there just as easily be a list of things not to do in Kotlin.
Feb 15, 2018 · Justin Albano
Thanks for the feedback and thanks for catching that. The typo has been corrected.
Feb 14, 2018 · Justin Albano
Hahaha. Thanks for the catch. Learned something new today (about the Havard Bridge). I appreciate the feedback, as well.
Feb 14, 2018 · Justin Albano
Thank you for the feedback. I'm glad you enjoyed the article.
Feb 14, 2018 · Justin Albano
Thank you for feedback. Glad you found it useful.
Feb 13, 2018 · Justin Albano
Thank you. I'm glad you enjoyed it. Thanks for the feedback.
Feb 12, 2018 · Justin Albano
Thank you. That is a great complement. I really appreciate it.
Feb 12, 2018 · Justin Albano
Thanks for the information. I decided to leave out a discussion of the TCK for this article due to length constraints, but you are right about both the TCK and existing reactive libraries. I tried to convey that the standard Java version is a common set of interfaces so that all of the implementations do not have to rewrite them (since they are all identical). I will add a mention that these interfaces are not intended for standalone use.
Again, thank you for the suggestion.
Feb 11, 2018 · Justin Albano
You are correct: That's a typo that should be "subscriber," not "subscription." Thanks for catching that.
Feb 10, 2018 · Justin Albano
Thanks for the feedback. Glad you enjoyed it.
Feb 10, 2018 · Justin Albano
Thank you for your feedback. I appreciate it.
Feb 09, 2018 · Justin Albano
Although there are multiple libraries that would solve the problem, I decided not to use them, as they would include 3rd party dependencies in the example and would hide details that accompany the explanation.
Feb 09, 2018 · Justin Albano
Thank you. I appreciate your feedback.
Feb 09, 2018 · Justin Albano
Thank you for the feedback.
Feb 09, 2018 · Justin Albano
I agree. It is also an overlooked step in that TDD process. Before moving onto the next feature, there should be some refactoring, if needed.
Feb 08, 2018 · Justin Albano
I appreciate the compliment. If I can improve in anyway, please feel free to let me know.
Feb 08, 2018 · Justin Albano
Thank you. I appreciate your feedback.
Feb 06, 2018 · Justin Albano
I have added an explicit mention of this brevity. Thank you again.
Feb 06, 2018 · Justin Albano
I understand. You are correct, for the sake of simplicity, I combined more than one responsibility into the serializer class. The logic for obtaining the fields to be serialized can be extracted and the JsonSerializer can be refactored to simply create a JSON string from a list of serializable fields.
These changes have been made on a new branch of the repository. This could also be taken one step further, where a strategy implementation can be injected into the serializer, depending on if JSON, XML, or another output format is desired.
Again, I really appreciate the feedback and your constructive criticism.
Feb 06, 2018 · Justin Albano
I apologize. One of the more common arguments (justifiably) against annotations is the use of the annotations themselves. So I can understand your point of view, what part of the JsonSerializer do you believe is a violation of the SRP?
Feb 06, 2018 · Justin Albano
Thank you. I appreciate the feedback.
Feb 05, 2018 · Justin Albano
Thank you for the feedback. You are correct that the annotations attached to the Car class do violate the Single Responsibility Principle (SRP). In general, annotations are an extra-object-oriented means of conveying information (more like meta-programming), but sometimes the trade-off may be worth it. For example, we could create an immutable CarDto class that has a toJson() method and accepts a Car object in its constructor. That would abstract the logic for JSON serialization into the CarDto class and leave the Car class to perform its domain logic.
While this technique maintains the SRP, it can become cumbersome when used in a large system. For example, if there are hundreds of domain classes, each with its own DTO class, it is easy to make a mistake (there is also a great deal of duplication). Whatsmore, it's easy to have the domain class and DTO fall out of sync. Using annotations, the serialization information is found within the class, and thus, is much more difficult to fall out of sync.
Which solution is better depends on the context of the problem being solved, so a developer would need to rely on his or her judgment to decide which option is better.
Feb 05, 2018 · Justin Albano
Thank you. Glad you enjoyed it.
Nov 29, 2017 · Hussein Terek
One of the simpler ways to describe pass semantics in Java is that all values are passed by value, even if it is more nuanced than that. In the case of primitive values, the immediate value (the 7 in int x = 7) is passed. In the object reference case, the reference is passed by value. Reassigning the reference does not change the original reference, but dereferencing it and changing the state of the dereferenced object does change the state of the shared object.
You are correct in saying that "objects" are not truly passed by value (the entire object is not "recreated" and no copy-constructor is invoked), but Java does not deal in objects per-say. Rather, it deals with "object references." Again, a simple way I use to teach the passing semantics of Java is that there are two fundamental, passable types: (1) primitives and (2) object references, and both are passed by value.
Nov 26, 2017 · Justin Albano
Thank you for your feedback. Yes, the VisualComponentFactory is an abstract factory. Many of the original GoF patterns blend into one another and the distinction between them starts to fade when they are applied to real systems. For example, if the factory method is made abstract and used in a non-abstract method, it can be simultaneously thought of as a step in a template method.
For the Encryptor interface, breaking the SRP depends on its purpose. Sometimes, encryption to disk may be a complex process (i.e. where is the key stored, how is it written to disk, etc.). To more clearly define the responsibility of the Encryptor, we could reduce the visibility of the creation method, thus turning it into more of a class with a template method (its main, externally visible responsibility would solely be the writing of encrypted data to disk). There are multiple ways to solve this problem, but in order to maintain the simplicity of the example, I opted to go with an answer that required a fewer number of classes.
Nov 25, 2017 · Justin Albano
Thank you for the feedback.
Nov 25, 2017 · Justin Albano
Thank you for the feedback.
Nov 22, 2017 · Justin Albano
I'm glad you enjoyed the article.
Nov 19, 2017 · Justin Albano
Thank you. I'm glad you enjoyed the read.
Nov 18, 2017 · Justin Albano
Although I agree that there are some flaws in the Java technique for generics (non-reified types, type erasure, etc.), it's still good, even for a Scala developer, to know this information as it plays a part in the development of the JVM bytecode to support generics.
Nov 18, 2017 · Justin Albano
Thank you! I appreciate the feedback.
Nov 18, 2017 · Justin Albano
Thank you for catching that: I inverted the direction of the composition to correctly follow the UML convention. Thank you for the feedback.
Nov 09, 2017 · Justin Albano
Thank you for the feedback. In the case you mentioned, Node.js checks if there are any completed promises and handles them. I've changed the article to use "completed" rather than "resolved" to make the point clearer. Thanks for bringing that to my attention.
Nov 03, 2017 · Justin Albano
Thank you for the feedback!
Nov 03, 2017 · Justin Albano
Thank you. I appreciate the feedback.
Oct 31, 2017 · Justin Albano
Glad you enjoyed it. Thanks for the feedback.
Oct 30, 2017 · Justin Albano
Java-based configuration is the norm now, but for this example, I used the XML-based alternative because it can be changed without having to recompile any code. The same can be done using a configuration file (as you mentioned with the application.properties file), but that type of change (albeit for reflection rather than the fields of a credit card) is covered in the reflection sections. The choice of XML was simply for brevity so that the example did not become focused on Spring rather than the pattern itself. You are correct in your thought process on how this would work in a real system.
Oct 30, 2017 · Justin Albano
You're very welcome. I appreciate the feedback. If there is anything that you wish to see more of (on this article or in general), let me know.
Oct 27, 2017 · Justin Albano
You're very welcome. Thank you for the feedback.
Oct 25, 2017 · Justin Albano
Thank you for the constructive feedback. I've updated the section on Passing Data in Java to make the fact that object variables store references more explicit. I also included an example of a primitive value (which holds the primitive literal) and an object (which holds a reference to the object) to illustrate the difference.
Oct 25, 2017 · Justin Albano
Thank you for the feedback. I appreciate it.
Oct 25, 2017 · Justin Albano
Thank you. I appreciate the feedback.
Oct 20, 2017 · Justin Albano
Thanks for the feedback. I agree that suppressing warnings should be a last resort. In cases where the warnings are difficult to resolve, such as unchecked casts, it may be necessary. First instinct should be to resolve the warnings, or else, change the situation to ensure that the warning is no longer applicable (i.e. upgrading a library so that an unchecked cast is no longer necessary). If all else fails, and we are aware of the warning, it can be suppressed or the settings for the IDE is changed.
The trick is to leave the code without warnings so that the next person comes along and has some pressure/tendency to leave it without warnings as well. The goal is to stop the following thought: "If there are already 10 warnings (and the project has a little caution sign on it already), what's another 1 or 2?" If changing the IDE settings solves that problem more effectively, go with it.
Oct 12, 2017 · Justin Albano
Thank you. Part 3 has been posted.
Oct 11, 2017 · Justin Albano
Good catch. I've updated the command to no longer include the "s": Thank you.
Oct 11, 2017 · Justin Albano
Glad you enjoyed it. Thank you for the feedback.
Oct 09, 2017 · Justin Albano
Part 2 has just been posted. Thank you for the feedback.
Oct 05, 2017 · Justin Albano
You're very welcome. Thank you for the feedback.
Sep 28, 2017 · Justin Albano
You're welcome. Thank you for the feedback.
Sep 28, 2017 · Justin Albano
The code for this tutorial can be found by clicking the Github image at the top. The URL is https://github.com/albanoj2/order-rest-backend.
Sep 26, 2017 · Justin Albano
The second part of this article can be found here. Part 3 and Part 4 also go into the implementation of the presentation layer and the deployment of the web service, respectively.
Sep 25, 2017 · Justin Albano
Hi Anna, thank you for your feedback. This part of the article focuses on the concepts in general, rather than the specific concepts as they pertain to Java. For that information (along with the specificity that you requested) can be found in Part 3 of this series.
Sep 21, 2017 · Justin Albano
Due to the length of the article, it has been divided into three parts. The first part (this article) focuses on the design and the thought process behind the development of the web service, while the second and third articles will focus on the implementation of the web service and testing the deployed service. Although creating a Spring web service is a short task, this series of articles take the time to delve into the systematic thought process behind making the web service. Our goal is not to create automatons that go through the motions: Our goal is to teach creativity and understanding of the fundamental decisions required to make a solid web service.
Sep 13, 2017 · Justin Albano
Thank you for the feedback. I tried to keep this series as concise as possible, which meant that I could not include all principles and best practices. Although composition over inheritance is a good principle, it is very nuanced (when to use it and when it is valid to use inheritance). Discussing it would require an article in-and-of-itself. Therefore, I left it out for the sake of focus and concision.
Sep 13, 2017 · Justin Albano
Thank you for the feedback. That is a fair point. I now added in a disclaimer that this null-terminated scheme is not how Java stores strings. Although it was my intent to demonstrate a generic memory scheme (in this case, the C string memory scheme), I did not make that point explicit. Thank you for helping me improve this article. It is much appreciated.
Sep 11, 2017 · Justin Albano
Thanks for the feedback. The next article in the series is posted here.
Sep 11, 2017 · Justin Albano
Thank you, Kunle. I'm glad that it's been useful. I appreciate the feedback.
Sep 07, 2017 · Justin Albano
Thank you for the input. Your insight is much appreciated.
Note that this article does not describe the actual implementations of memory management used by a JVM, but rather, a general scheme that is used as the basis for memory management.
Sep 05, 2017 · Justin Albano
Thanks for the feedback, Gemma. Are you looking for a video tutorial simply walking through how the specification was created, or walking through the thought process behind each of the additions to the specification?
Sep 05, 2017 · Justin Albano
Hi QingYu, I do not mind, but I would contact a DZone representative to make sure that DZone is okay with translating an article on their site.
Jul 21, 2017 · Justin Albano
Okay, now I understand what you are saying. The case I stated before is a templated class (i.e. C++ or C#), but you are right, generics in Java do not incur any runtime overhead since they are erased.
Jul 21, 2017 · Justin Albano
To my understanding, there is a type created to represent generic, with the actual type filled in. For example, a type similar to CustomCloneable_with_Vehicle, since the type information must be represented at runtime once the type has been erased. I would need to inspect the actual bytecode generated to see where this generation takes place and how much bytecode is generated. For example, if we had a Car and Truck class that subclassed Vehicle, I'm not sure if there would be a CustomCloneable_with_Car and CustomCloneable_with_Truck class generated, which represents 2 more classes than the non-generic technique. (I don't have a specification, but there's a mention of it in the tutorials.)
In this particular case, or especially when the top-level interface, such as Cloneable, is not modifiable, then covariant return types are a simple option (or the only option, since the top of the hierarchy does not have a generic parameter).
Again, I appreciate your feedback: I've learned a lot from it.
Jul 21, 2017 · Justin Albano
For the new type, I mean that bytecode must be generated to represent each of the implementations. For example, a CustomCloneable<Car> type must be generated by the JVM. This process gets repeated for each of the types that are passed into the generic. At a JVM level, there is more that must be done to support generics (type erasure, etc.) rather than a simple compile-type constraint such as covariant return types. That's not to say that generics and covariance with generics aren't useful, but for the purpose of this article, I used the simpler route to demonstrate the principle.
For the "Joint-Union" terminology, it's more colloquial:
https://www.reddit.com/r/programming/comments/1fr8fv/little_known_java_feature_joint_union_in_type/
I agree with you, though: This technique is an intersectional generic type. I've updated the article to reflect the better terminology. I even included your link for reference. Thank you. I appreciate your feedback and helping me improve the article.
Jul 21, 2017 · Justin Albano
Thank you. I'm glad it was helpful.
Jul 21, 2017 · Justin Albano
I avoided generics because they didn't add any capability. In fact, they would have added bloat, since the subclasses would have extended CustomCloneable<T extends Vehicle> when they could have just as easily have extended CustomCloneable (the non-generic form). Using generics would have also created a new type for each and every class that performs a covariant override, rather than derive from a single class (creating a cohesive class hierarchy).
As for the Joint-union types, you are correct: In following the vernacular of set theory, the generic types are intersected, but after doing some research, the most common name I found for that technique was "Joint-union." I did not create the name, I simply followed existing nomenclature.
Jul 20, 2017 · Justin Albano
Thank you for the feedback. The error has been corrected.
Jul 20, 2017 · Justin Albano
Thank you, Paul. Your feedback is greatly appreciated.
Jul 20, 2017 · Justin Albano
By overriding the Object::clone method, there would have involved the restriction of the exception types thrown, since Object::clone throws a CloneNotSupportedException in its declared signature. I did not want to involve the restriction of the exception type (for brevity, I would have removed the declared exception from the overridden signature).
Instead of mentioning qualifications on the overridden method, I wanted to avoid it entirely. Introducing Object::clone would have muddied the waters of the simple covariant example.
Jul 19, 2017 · Justin Albano
Thank you. I appreciate your feedback.
Jul 19, 2017 · Justin Albano
Thank you. And good catch. The CustomCloneable method is correct, but the overridden method is incorrect (it should be customClone). I didn't use the clone() method because it would implicitly override the Object::clone() method and would confuse the intent of the code snippet.
Feb 11, 2016 · Matt Werner
Interesting take. It was made even worse in C and C++, where NULL was only a directive for the integer value of
0
. A very perplexing problem was the creation of two methods, one that accepted an int and another that accepted a pointer:If a value of NULL was supplied to
someMethod
, which one was called? C++11 solved this by introducing an entirely new construct that represented a null pointer:nullptr
.Jan 20, 2016 · Justin Albano
You are correct. For the sake of brevity, I did not include synchronization logic for the list of animals, since there is superfluous to the observer pattern itself. In order to protect against this race condition, you would need to add some means of synchronization mechanism (such as in this Stackoverflow post).
Again, your observation is correct, but since we can have an observer pattern without access to a list of managed objects, this is left to the reader as an exercise.
Jan 18, 2016 · Alex Theedom
Very useful way of creating a known set of strategies. The upside is that this approach is that the operations known now can be implemented without the boilerplate code of creating a new class for each operation, but this still allows for extension (future operations can be created; i.e., this approach does not stop others from creating their own operations).
Thanks for the cool approach!