Showing posts with label simplicity. Show all posts
Showing posts with label simplicity. Show all posts

Saturday, July 9, 2022

Just use Dictionaries

A Python dictionary has a simple & well-known API. It is possible to merge data using a nice & minimalistic syntax, without mutating or worrying about state. You're probably not gonna need classes.

Hey, what's wrong with classes? 🤔

From what I've seen in Python, classes often add unnecessary complexity to code. Remember, the Python language is all about keeping it simple.

My impression is that in general, class and instance-based code feels like the proper way of coding: encapsulating data, inheriting features, exposing public methods & writing smart objects. The result is very often a lot of code, weird APIs (each one with its own) and not smart-enough objects. That kind of code quickly tend to be an obstacle. I guess that's when workarounds & hacks usually are added to the app.

Two ways of solving a problem: class-based vs data-oriented.
Less code, less problems.

What about Dataclasses?

Python dataclasses might be a good tradeoff between a heavy object with methods and the simple dictionary. You get typings and autocomplete. You can also create immutable data classes, and that's great! But you might miss the flexibility: the simplicity of merging, picking or omitting data from a dictionary. Letting data flow smoothly through your app.

Hey, what about Pydantic?

That's a really good choice for things like defining FastAPI endpoints. You'll get the typed data as OpenAPI docs for free.

I would as early as possible convert the Pydantic model to a dictionary (using the model.dict() function), or just pick the individual keys and pass those on to the rest of the app. By doing that, the rest of the app is not required to be aware of a domain specific type or some base class, created as workaround for the new set of problems introduced with custom types.

Just data. Keeping it simple.

What about the basic types? 🤔

That is certainly a tradeoff when using dictionaries, the data can be of any type and you will potentially get runtime errors. On the other hand, is that a real problem when using basic data types like dict, bool, str or int? For me, I can't remember that ever has been an issue.

But shouldn't data be private?

Classes are often used to separate public and private functionality. From my experience, explicitly making data and functionality private rarely adds value to a product. I think Python agrees with me about this. By default, all things in a Python module is public. I remember when learning about it, and the authors saying that’s okay because we’re all adults here. I very much liked that perspective!

Do you like Interfaces? 🤩

Yes! Especially when structuring code in modules and packages (more about that in the next section). Using __init__.py is a great way to make the intention of a small package clearer and easier to grasp. Maybe there's only one function that makes sense to use from the outside? That's where the package interface (aka the __init__.py file) feature fits in well.

Python files, modules, packages?

In Python, a file is a module. One or more modules in a folder is a package. One or more packages can be combined into an app. Using a package interface makes sense when structuring code in this way.

Keeping it simple. 😊

I'm finishing off this post with a quote from the past:

“Data is formless, shapeless, like water.
If you put data in a Clojure map, it becomes the map.
You put data in a Python list and it becomes the list.
Now data in a program can flow or it can crash.

Be data, my friend.

Bruce Lee, 1940 - 1973

ps.

If neither Bruce or I convinced you about the great thing with simple data structures, maybe Rich Hickey will? Don't miss his "just use maps" talk!

ds.



Top photo by Syd Wachs on Unsplash

Monday, January 11, 2021

Simple (within parentheses)

  • - Hey, what's ClojureScript?
  • - It's a thing that compiles Clojure to JavaScript.
  • - I get it. What's Clojure?
  • - It's a Lisp.
  • - ???
  • - You know, a functional programming language that uses a lot of parentheses.
  • - I … get it? 🤯

Don't worry. In this post, I will share some of the basics that I have learned about Clojure and ClojureScript.

Clojure?

With Clojure, you can write simple, functional and minimalistic code. Some of the cool things with Clojure are:

  • data is immutable
  • the REPL is a powerful tool
  • few keystrokes to make things happen

Clojure runs on top of Java, suitable for all kinds of "backend" things. It also runs on top of JavaScript. Yes, JavaScript - making it possible to develop all kinds of apps, tools, products and websites. There's even an option to run in a .NET runtime, but I haven’t tried out that one yet.

What does it look like?

Even though the syntax may look unfamiliar, you can already see in this silly example the less amount of keystrokes needed using Clojure, compared to JavaScript.

Parenthesis?

Everything you write in Clojure is a list, wrapped in parentheses. That may sound weird. I agree, it is weird. But your eyes will get used to it. In short, the format of writing something in Clojure is:

(operator operands) or even (function arguments)

Here is an example:

... and how it would be written in JavaScript:

If all this is new to you, you might have this expression in your face right now: 😬

That is perfectly normal. I have looked like that a lot during 2020. When digging deeper, you may need to go through The 12 Stages of Learning Clojure.

ClojureScript?

With ClojureScript, you develop web apps and write simple React components. You write code in Clojure, compile it to native JavaScript and run it in your favorite browser. The compilation happens all the time and automagically as you type.

Just like with Java or .NET in the backend, ClojureScript has native access to JavaScript. You can use and interact with your favorite npm packages and React components just as you would with JavaScript.

Reagent and React

I'm going to fast-forward a bit by adding a ClojureScript library called Reagent. With Reagent, you write React components but with Hiccup instead of JSX. Wait, what?

View components are built up using Clojure data structures. The example above creates html elements with Clojure vectors and keywords. This style is called Hiccup. It will save you a lot of keystrokes and you'll have a lot less of scrolling in your code editor.

What about state?

I'll fast-forward again by adding a very nice library called re-frame.

From the re-frame docs:
“... It has reactivity, unidirectional data flow, pristinely pure functions, interceptors, coeffects, conveyor belts, algebraic effects, statechart-friendliness and claims an immaculate hammock conception. All while being both simple and easy. ...” 💥🤯💥

With re-frame, data is stored in one place called the "app db". Your components will fire events and subscribe to changes in the app db. The cool thing is that you write code in a sequential way, making it very readable and easy to understand. However, the syntax of the actual events and subscriptions might take a while to understand, at least if you are new to Clojure in general.

Here, we have a Reagent component that adds a button component, only when the app is disconnected. It is subscribing to changes of disconnected in the app db. React will re-render the components when the app state has changed.

Cool, but can I use my favorite editor?

Yes, most likely. I know there are Clojure plugins for VS Code, Atom, Sublime Text and intelliJ. I use Emacs, because ... I just like it.

There is something important and special going on with developers and their text editors. I think you will be able to find your favorite dev setup. I also think that you will learn a lot of new programming concepts and styles when reading more about this cool language and its libraries.

Photo by Marcos Paulo Prado on Unsplash