Pattern recognition
Originally posted on 2019-10-09 as an email
#articles
Hey cool kids!
This issue focuses on pattern recognition. “Great”, I hear the voice inside your head, “finally he’s gonna talk about all that fancy ML stuff, right?”
Hahahahaha no. We’re gonna talk about like, actual development? ML is cool and all but I’m not the expert to talk about it. We may get such an expert in this very newsletter though, so stay tuned!
Woah, all this misleading kinda starts to sound like fake news. But then again, I don’t think most people want to live in a world where you can only post things that tech companies judge to be 100 percent true
Are you gonna be taking weekly stabs against Mark now? Stop
No. But he just keeps on giving! Did you actually hear the Georgetown speech? It’s almost like Steve Jobs’ inspirational graduation speech, only reversed and fucked up.
sudo stop
Nope, not working
sudo -u#-1 id -u OR sudo -u#4294967295 id -u stop
Ok. Holy shit that actually worked!
Did you see the Joker yet? Great movie right?
Yes! Apparently the co-founder at GitLab thought his business too needed some chaos, only to be promptly thwarted the next day by the chief marketing officer (which sounds like a really stressful job) and his trusty sidekick. Back to the Arkham with ya!
So, about those patterns?
Well, do you know what is GoF?
Baby don’t hurt me?
No, GoF, (Gang of Four, not the band, not the political exiles, not one of the 1783 Pornhub search results) are the original authors of the “Design Patterns” book, quite possibly one of the most monumental books in the history of software.
What are design patterns and why should I use them?
Design patterns help you tackle common problems, without your code base blowing out of control. They represent industry standards and often graduate to be built-in language features. Design patterns are mostly found in more mature languages, or those that deal with the enterprise, as that’s where they have the most impact.
Ok, I knew most of that already. So I should just use them everywhere, right?
Absolutely not. These patterns are there to deal with problems. Over time you will start to discover more and more applications and how effective they really are. But it’s important to first identify the problem, then the patterns which could address it, then understand if and how you would need to adapt them. Applying a “good practice” blindly is sure to turn it into a bad practice.
Can you give me some examples?
Absolutely! Let’s take a look at some of the patterns stated in that answer, with a bit more context and 10 years of hindsight. Examples are Java-like, but no real language.
Factory
This pattern has a lot of sub patterns, but I will group their core functionality here. Factories deliver new instances of a ready-to-use object. This object may be precustomized in what is called an “opinionated default”, but other than that, the factory doesn’t offer much customization. The factory itself may often be a Singleton.
Example:
Factory toyotaFactory = new ToyotaFactory()
Car toyota = toyotaFactory.newCar()
Builder
The builder pattern is, on the other hand, about customization. You start with an “empty” object, then along the way you apply to it all the stuff you want. Very handy for when you need to support very different and customizable instances of the same object.
Example:
CarBuilder toyotaBuilder = new CarBuilder()
Car toyota = toyotaBuilder.color(Color.RED).windows(Windows.ELECTRIC).abs(true)
.gps(true).childSeat(false).build()
We could also have a CarBuilderFactory creating CarBuilder instances, as the CarBuilder class seems to require little customization itself (builders are often like that). Quite often btw the CarBuilder class and the Car class are different and you don’t actually have a Car instance until you call “build()” itself.
Singleton
Create a single instance of a particular object, for the entire program. This is one of the most used patterns out there, but over time has often been criticized as unsafe, bad design, and most implementations of it suffer by some sort of concurrency issue. Languages such as Kotlin, or C#, have the singleton pattern already implemented and even a keyword. However, this is usually the wrong pattern to use. It looks simple and you may even have an ok implem of it. But there is probably a better design option.
Example:
Yeah, no
Facade
This pattern is not so common, but I’ve opted to include it here, because my current project at work involves getting rid of a gigantic Facade/Gateway mess. When a pattern is abused (usually something that happens over time as the requirements evolve but the architecture doesn’t), it ends up being an active hindrance to the developer. Some signs of a failing design pattern are:
- Confusing architecture
- Multiple layers that do very little actual work
- Code that exists only to maintain a similar structure to other code, not because it’s ideal/useful
It’s important to remember a pattern is supposed to deliver value. Panos Lantavos has elegantly put this as “Architecture over functionality”, which is a plague in the enterprise world. This is not a choice you should have to make and if you are, you’re using the wrong pattern. But do not underestimate the brains of the people who developed and implemented those. They were solving real world problems and sometimes they even had to choose between bad and worse. Assume they chose wisely, until you can reliably prove otherwise.
Observer
Hugely popular and the heart of many major frameworks/applications. Also called the publisher/subscriber model, you will most commonly find it in what is called a “Message Queue” system. Message Queues (MQs) provide an asynchronous communications protocol, meaning that the sender and receiver of the message do not need to interact with the message queue at the same time. Messages placed onto the queue are stored until the recipient retrieves them. Message queues have implicit or explicit limits on the size of data that may be transmitted in a single message and the number of messages that may remain outstanding on the queue. That’s totally copy/pasted from my article on MQs btw, coming out soon!
Examples:
RabbitMQ, Apache Kafka
Circuit Breaker
Not in the original GoF book, this is a very interesting pattern (and a personal pet peeve). I hope you read that last link, because that’s Martin Fowler. Use this pattern to safeguard against cascading failures in complex systems. Essentially the logic is “every time you get a minor (recoverable) failure, increment a counter. If there are no failures for a while reset the counter, When a counter limit is reached, shut down your system”. Even defining the logic requirements for this pattern’s application will be a very illuminating view into your system, what to expect and what are its conditions and possible states.
Example:
while (true) {
circuit.reset()
if (Network.isUnavalable())
circuit.add(1)
if (Drive.isInaccessible())
circuit.add(1)
if (System.isUnresponsive())
circuit.add(1)
if (circuit.get() > 2)
throw new CircuitBreakerException("Failure threshold exceeded")
sleep(100 ms)
}
But I write in beautiful Haskell/Clojure/Lisp! I don’t need these.. (scoffs)… patterns
First of all, noone ever called Lisp beautiful, so don’t start that shit here.
Secondly, patterns are a tool that depends on the implementation. Your language may make some things easier, or even unnecessary. It may make others essential. Knowing well thought-out algorithms to tackle common problems can only be a benefit… as long as you are also measured and careful in the way you apply them.
Final note: I’m evaluating whether I will stay longer in CERN, or search for something else. This section aims to give you some insight in how I search for work. As part of that effort, I’ve updated my CV across Europass, LinkedIn, StackOverflow careers and my github profile website. I also marked myself as “actively looking” in those platforms, who are, in my experience, the best starting (and ending) point in that search. Will probably update with more info next week!
That’s all from me, and hope you had/have a great weekend!
Cheers,
Alexander P.