> Most systems handle this defensively with locks and runtime validation. So i work at an org with 1000s of terraform repos, we use the enterprise version which locks workspaces during runs etc. everywhere else i’ve worked, we either just use some lock mechanism or only do applies from a specific branch and CI enforces they run one at a time. My question is: who is this aimed at and what problem is it actually solvin…
Hello, CTO of Terrateam here, the creators of Stategraph. As you said, the common practice is to use locks on state to guarantee that operations don't step on each other. This works, however the cost is that if it takes 5 minutes to perform an operation, only one person can be doing an operation at a time, so if 5 devs are modifying infrastructure, the last one has to wait 25 minutes just to get back the plan, even i…
We chose OCaml to write Stategraph
91–100 of 127 posts
Re: We chose OCaml to write Stategraph
#92Earlier quoted context omitted.
> The concurrent applies isn’t that big of a deal? That depends. There are many organizations (we talk to them) which have plans and applies that take 5 - 10s of minutes, some even close to an hour. That's a problem. We talked to one customer that a dev can make a change in the morning and depending on the week might have to wait until the next day to get their plan, and then another day to apply it, assuming there a…
> There are many organizations (we talk to them) which have plans and applies that take 5 - 10s of minutes, some even close to an hour. That's a problem. We talked to one customer that a dev can make a change in the morning and depending on the week might have to wait until the next day to get their plan, and then another day to apply it That's us. Especially because our teams are distributed across NA/Eastern Europe…
Re: We chose OCaml to write Stategraph
#93I have worked with Haskell, Scala, and OCaml; they all bring the joy of programming into daily tasks, and OCaml has a fast compiler and a great module system. This makes it a really fun and effective language to use.
Scala has some quirks but I enjoyed it relative to more popular languages and its apparent stagnation makes me sad.
Re: We chose OCaml to write Stategraph
#94Earlier quoted context omitted.
Those two type systems are not the same. Typescript has some soundness issues in the type system. They are there because they have to work seamless with javascript so it's understandable. And they improve many codebases that would have been otherwise written in javascript. But they do not in any way give you the same level of guarantees that OCaml, Haskell, or Rust would give you.
For all practical purposes I believe it does the same thing.
Re: We chose OCaml to write Stategraph
#95Re: We chose OCaml to write Stategraph
#96Earlier quoted context omitted.
Using something you enjoy is fine, as long as you don’t forget the person who is going to maintain your code after you move on.
Imagine inheriting a project that was a joy for someone to work on instead of a slog.
Re: We chose OCaml to write Stategraph
#97TIL (via a rabbit hole after reading this) that a good type system removes an absurd amount of boilerplate validation code.
Do you have any good resources on this subject? I agree and would like to see what a persuasive argument for it looks like.
(*
Quick note on notation: I will use "double quotes" when referring to _values_ and `backticks` when referring to _types_.
*)
(*
Think of this as an interface. It defines the shape of a module. Notice that the interface describes a module that defines a type called `t`, and two values: "of_string", and "to_string", and they are functions with types: `string -> t`, and `t -> string`.
*)
module type ID = sig
type t
val of_string : string -> t
val to_string : t -> string
end
(*
Below this comment is a module named "Id" that _is of type_ (in other words: it _implements the interface called_) `ID`. Due to the explicit type annotation (Id : ID), now from the perspective of anywhere else in the code, the exported interface of the module "Id" is `ID`.
Modules only contain two things: `type declarations`, and "values". Values are your primitives such as 1, ' x + 1), (Some x), f x, { foo = "bar"; baz = 42 }, and even (module Id) (yes! modules can be values too!). Type declarations tell the compiler . Anything which is a value _always_ has a type that can _usually_ be inferred.
No type annotation is necessary when the compiler correctly deduces the type of your value through static analysis. For instance, in the module below, "of_string" is deduced to be of type ('a -> 'a). The ' on the symbol 'a signifies a "type variable", and it means that it can be filled in with any type. For instance (t -> t) and (string -> string), but not (t -> string) or (string -> t). For those it would have to be of type ('a -> 'b). We cannot deduce this type, however, because our implementations do nothing with their inputs besides return them. Since nothing is changed, it's always the same type.
Now, can you spot the pink elephant? Notice how the "ID" interface from above defines "of_string" to be of type (string -> t). How can this be possible? It's because we gave the compiler a hint when we said `type t = string`. This says that a "value" of type `t` is backed by a value of type `string`. If something type checks as `t`, it also type checks as `string`.
So, we could reason through and say ('a -> 'a) can be instantiated to (t -> t), but `t` is also equal to `string`, so we can mentally imagine a hypothetical intermediate type... something like ({t,string} -> {t,string}). This type and type equality is visible _inside_ the module. But when the `ID` interface was applied over the `Id` module as in (Id : ID), this has the effect of hiding the type equality (the fact that `type t = string`) because in the `ID` interface we define `t` without an equals sign: `type t`. This forces us to _choose_ a concrete type to expose externally, even though the type is less general than what the implementation sees.
NOTE: OCaml doesn't use parens for function definition or application. Compare this OCaml code against its Python equivalent.
> let hello_world h w = (h, w)
> let h, w = hello_world 1 2
vs.
> def hello_world(h, w):
> return (h, w)
> h, w = hello_world(1, 2)
*)
module Id : ID = struct
type t = string
let of_string s = s
let to_string s = s
end
let main () =
let s = "abc123" in
let id = Id.of_string s in
(* NOTE(type error): because the built-in "print_endline" function is of type (string -> unit) and not (Id.t -> unit) *)
(* NOTE: if an expression returns unit, you don't need to create a let binding for it. You can simply tack a semicolon to the end of it if you need sequence another expression to follow it. *)
print_endline id;
(* okay *)
(* STDOUT: abc123 *)
print_endline (Id.to_string id)
;;
main ()
You could imagine implementing this pattern of defining parsers such as "of_string", "of_bytes", "of_json", "of_int", "of_db_row", "of_request", for any piece of input data. You can think of all of these functions as static constructors in OOP... you take in some data, and produce some output value: e.g. "of_string" takes in a `string` and produces a `t`.Now, if you have a bunch of "values" of type `t`, you know that they _only_ could have been produced by the `of_string` function, because `of_string` might be the _only_ function that ends with `-> t`. Therefore, all the values maintain the same properties enforced by the `of_string` function (similar to class constructors in OOP). With this, you can create types such as `Nonnegative.t`, `Percent.t`, `Currency.t`, `Image.t`, `ProfilePicture.t`, and parsers from another type to the newly minted type.
The compiler can help you enforce these properties by providing guardrails in the form of static compiler checks (these checks are run _before_ your code can even be compiled). If I have a value of type `Nonnegative.t`, then not only do I not need to validate that it's not negative, I also don't have to validate that it's not negative everywhere else that values of that type are used -- the validation logic is baked into the constructor. Parse, don't validate.*
Re: We chose OCaml to write Stategraph
#98Earlier quoted context omitted.
Scala has some quirks but I enjoyed it relative to more popular languages and its apparent stagnation makes me sad.
Scala just seems to have an ever changing identity. Scala 3 drastically changed syntax and now they're trying to move the language from monads to effects.
Re: We chose OCaml to write Stategraph
#99Earlier quoted context omitted.
> There are many organizations (we talk to them) which have plans and applies that take 5 - 10s of minutes, some even close to an hour. That's a problem. We talked to one customer that a dev can make a change in the morning and depending on the week might have to wait until the next day to get their plan, and then another day to apply it That's us. Especially because our teams are distributed across NA/Eastern Europe…
If there was a time to insert a Jobs "you're holding it wrong" I think it would be here...
Re: We chose OCaml to write Stategraph
#100Earlier quoted context omitted.
> I think we should normalize saying that tech stack choices are subjective and preference-based. We're not robots. The social and aesthetic parts of a stack matter to people I would just like to distinguish "subjective and preference-based" from "social and aesthetic" and also clarify some notions. 1. The social is objective. We are social animals. It is essential to what it means to be human. We need social relatio…
I’m sorry but there is no way you can demonstrate a universal aesthetic. Your opinion of other people’s tastes does not reflect on their taste — it reflects on yours.
What do you mean by "aesthetic", because I've already made the distinction between objective beauty and subjective taste. If my explanation is true, then it follows that there is an objective ordering of beauty (of at least two kinds: with respect to the same form/end, and between forms and ends). Then, there's the question of how competent someone is at recognizing this order. And finally, there are contingent factors that will affect expressed volitional preference as a function of factors like attainability or character flaws or whatever.
Making beauty a matter of purely subjective response makes it more mysterious and nonsensical, not less.
> Your opinion of other people’s tastes does not reflect on their taste — it reflects on yours.
How do you know this? You haven't demonstrated this claim. I've at least explained the basis for mine.
I claim that on the contrary, yes I can. I can claim that someone who thinks rape or murder are beautiful has objectively deranged tastes, because these acts are intrinsically ugly.