ProgrammingPro #2: ReAct Pattern for LLMs, LangChain, GoLand 2023.1, and Software Anti-Patterns
Hi,
Hello and welcome to second issue of the ProgrammingPro newsletter! In this newsletter, we’ll be detailing the most relevant industry insights, actionable tutorials, and useful tools and resources for developers and software engineers.
In today’s issue:
News and Analysis
Secret Knowledge: Articles & Trending Repos
Tutorial: Examining Typical Software Anti-Patterns
Upcoming Developer Events
You’re receiving this newsletter because you’ve previously provided Packt with your email. We hope that you find this newsletter valuable and informative, and a way to stay up to date as new AI technologies change the world around us. If it’s not the right area for you, please click on the unsubscribe button at the footer of this email. Please also consider taking the short survey below to share your thoughts and you will get a free PDF of the “Flutter Projects” eBook upon completion.
Kind Regards,
Kartikey Pandey
Editor-in-Chief
Complete the Survey. Get a Packt eBook for Free!
News and Analysis
What’s New in GoLand 2023.1: GoLand is a popular IDE in the Go space. The latest version introduces a vulnerability checker and vulnerable package updater, improved gRPC tooling, and the ability to run ‘scratch’ files with non-standard-library packages.
Chrome Ships WebGPU: WebGPU is now available by default in Chrome 113, which is currently in the Beta channel. WebGPU is a new web graphics API that offers significant benefits including reduced JavaScript workload for the same graphics and more than three times improvements in ML model inferences.
Python 3.11.3, Python 3.10.11 and 3.12.0 Alpha 7 Released: Another set of Python releases are available. More importantly, Python 3.12 will be released in October 2023. Even though October is still months away, you can already preview some of the upcoming features, including how Python 3.12 will offer even more readable and actionable error messages.
What’s New in React 18: An easy to follow slidedeck of a presentation given at last week’s React Ahmedabad meetup.
Announcing GoReleaser v1.17: Packed with some juicy features and and quality-of-life improvements, the motivation for GoReleaser is to simplify the release process by building binaries for multiple platforms, creating a GitHub release.
Databricks Releases Dolly 2.0: This is the first open source, instruction-following LLM for commercial use.
Secret Knowledge: Articles & Trending Repos
Python implementation of the ReAct pattern for LLMs: This article describes a simple Python implementation of the ReAct (Reason + Act) pattern. You can implement additional actions that an LLM can take - searching Wikipedia or running calculations for example - and then teach it how to request that those actions are run, then feed their results back into the LLM.
LangChain: Large language models (LLMs) are emerging as a transformative technology, enabling developers to build applications that they previously could not. But using these LLMs in isolation is often not enough to create a truly powerful app - the real power comes when you can combine them with other sources of computation or knowledge. This library assists in the development of those types of applications with LLMs through composability.
Groovy Datasets for Test Databases: When you experiment with a new-to-you data science skill, you need some sort of data to work with. This article talks about several available data sets you can use when you practice your coding skills.
Croner — Cron for JavaScript and TypeScript: Trigger functions upon the schedule of your choice using the classic cron syntax. Works in Node, Deno, Bun and the browser, across time zones, offers error handling and overrun protection, and more.
What are Source Maps? Learn how source maps can help you debug your original code instead of what was actually deployed after the build process.
Building And Distributing A macOS Application Written in Python: If you’re writing for multiple platforms, Swift may not be your best choice. So how do you do Python applications on macOS? Read on for the latest update to this advice from Glyph.
Tutorial: Examining Typical Software Anti-Patterns
The literature on software anti-patterns is full of different kinds of anti-patterns, some of which have very funny names, even though their impact is anything but funny. Sometimes anti-patterns can be the result of a lack of discipline in providing tested, well-structured, and maintainable code to colleagues. An often-used term today in this field is clean code. The following sections will explore some common anti-patterns that can be found in code bases, more specifically in method implementations.
Spaghetti code
Multiple factors may contribute to an application code base appearing very unstructured: that’s the first sign of a code smell. In such cases, one of the most famous anti-patterns, spaghetti code, tends to appear. Spaghetti code may remain overlooked due to the fact that interfaces still remain coherent, but their implementation will contain long methods with interconnected dependencies.
class VehicleSpaghetti {
void drive(){
/*
around 100 lines of code
heavily using the if-else construct
*/
...
The above code is an example of an unclear drive() method that contains logic for everything from engine control to brake checks.
In such a state, it is nearly impossible to extend the application or verify its functionality. Sometimes, such code may become legacy code, which people will then use as an excuse. Such excuses will not contribute to the application’s success; the solution lies in refactoring and cleaning up the code base.
Cut and paste programming
This anti-pattern is perhaps another of the most common ones, where previously developed code is used to address the next challenge. This may seem like a smart reuse of code, but it can very quickly turn into a maintenance nightmare because the initial implementation conditions are completely ignored. This is a problem especially when the initial code was already anti-pattern-prone and ignored the principles mentioned in the previous chapters. The reuse of already-generated code should be done wisely in order to provide good protection.
Blob
This pattern can be identified in many older monolithic systems and applications. Nowadays, developers will claim that the problem has been overcome. The truth is not so certain. Not even frameworks are resistant to this anti-pattern. An anti-pattern can also be presented by a package that contains the most essential collection of divine classes or just one, the God class. This anti-pattern can often reside in classes called controllers, which control the entire behavior of an application. Such controllers accumulate a large number of different methods with different functionalities, meaning that the separation of concerns can end up being forgotten.
class VehicleBlob {
void drive(){}
void initEngine(){}
...
void alarmOilLevel(){}
void runCylinder() {}
void checkCylinderHead(){}
void checkWaterPump(){}
}
The above instance of VehicleBlob attempts to control each possible part.
A counterargument regarding the hypothetical maintainability of the code base could be considered invalid because such code might be difficult to test, perhaps even impossible. A similar problem can occur when the singleton design pattern is improperly overused. Once the blob anti-pattern is identified, it’s a great time to start thinking about creating simple diagrams supported by refactoring the source code before it’s too late.
Lava flow
Clean code is sometimes used as a deep term. Nowadays, it is becoming a common practice to push a proof-of-concept application directly into production without further thought. This anti-pattern arises when incompatibility or extensibility problems start to appear. The fact that the proof of concept verified a possible solution does not guarantee that it was prepared for production according to common development principles and techniques. This anti-pattern can be identified by the occurrences of long implementation classes whose purpose has been lost over time, but everyone is afraid to remove them because it might affect the system. This anti-pattern was named after lava, a hot liquid that flows down a volcano until it catches fire. In the era of microservices, distributed systems, and cloud solutions, an example of shared functionalities, such as libraries or solutions, can be considered. When such a pattern emerges in the development process, it may be a good time to re-evaluate the design of the code base, perhaps draw some diagrams, and apply conclusions to mitigate the possibility of a fire.
Functional decomposition
The functional decomposition anti-pattern may seem outdated due to the use of modern frameworks and the fact that the anti-pattern is better known in the field of procedural languages. The reality may be slightly different, as many legacy systems were migrated without sufficient understanding of the code base and business logic. Identifying the anti-pattern is trivial, as it’s impossible not to notice a code base containing many classes with a single responsibility, a lack of abstraction, and big cohesion. The root cause of this anti-pattern may be a lack of understanding of the basic principles of object-oriented programming or a misunderstanding of the application’s goal. The solution is to refactor the code base according to the required abstraction level while keeping in mind programming principles.
Boat anchor
Sometimes an application or a newly developed piece of software may inherit an outdated abstraction that becomes unnecessary. This abstraction can turn into a bottleneck not only because it requires maintenance but also because it can easily be replicated widely across a code base. The worst case can be the large utilization of this abstraction inside shared libraries or application modules. The anti-pattern can accelerate the degradation of the application code base at various levels.
One easy way to mitigate this is to keep in mind the SOLID design and APIE principles to allow for continuous refactoring. This enables the utilization of previously learned design patterns.
Conclusion
Being able to identify and describe some of the most common deviations from well-known principles and approaches brings value to any project. In this subsection, we have examined anti-patterns and proposed solutions to keep your code base maintainable and readable. The last point we want to make in this section is about the proper naming of methods, fields, and classes, which can significantly improve readability and maintainability and limit the misunderstanding of API use. Proper naming is also important as it allows a good understanding of UML diagrams. The next section takes us more into source code architecture.
This tutorial is an extracted piece from the book Practical Design Patterns for Java Developers written by Miroslav Wengner and published by Packt Publishing in February 2023.
Upcoming Developer Events
PyCon DE & PyData Berlin 2023: April 17 to April 20, 2023
PyCon US 2023: April 19 to April 28, 2023
Google I/O 2023: Live from Mountain View, CA on May 10, 2023