(I'm genuinely curious, independent of my newbie elixir evangelism)
577 karma · joined September 11, 2018
(I'm genuinely curious, independent of my newbie elixir evangelism)
With the BEAM, it is easy to create fully independent process trees. The architecture enables it. In fact, you can pull in dependencies and add them as "OTP applications" (which is in essence a fully independent process tree, doing its thing.)
The BEAM lends itself very well to structuring parts of your application as independently supervised process trees.
This is similar to microservices, where each microservice represents a fully independent process tree, with which you can only communicate via well-defined interfaces.
As I said, the author's comparison to Microservices is very unfortunate.
I'd say, yes, there are a lot of lessons buried in old code, but often, there is an equal amount of baggage we are too fearful to abandon because of backward compatibility and "bug became feature"-situations.
And even then, it's not you who is abandoning that, which makes the attitude even more baffling to me.
I mainly did refactoring on that day, so I had to make decisions by myself, anyway.
Went on a berserk coding spree from 1PM to 1AM with some small breaks in between. Completely cut off from any distraction, I was able to concentrate.
Willpower and discipline are nice, but real restrictions that are impossible to circumvent are better, at least for me.
Is there anyone out there who can answer this?
- in REST, you have no default way of querying data related to the current path. Of course, you can use frameworks for that (filtering, hydrating references, etc.). In GraphQL, you have entry queries and the rest is graph traversal, and that is basically the default (and of course, it does come with its disadvantages)
- on auto-generated schema: the interesting thing here is not whether you have auto-generated schemas etc. at all, but how well the data relations can be surfaced, explored and accessed on the API level. GraphQL enabled this in a different way compared to REST, and I would dare say it is a more delightful way.
As a client, given a Swagger API Documentation and a GraphQL Schema, I would prefer exploring the GraphQL Schema, just to find out what the API is about.
This allows adding metadata such as dates, descriptions, authors, type, etc. without much hassle.
This requires investing in some own CLI tooling, since creation and rendering should be automated for this.
Not quite sure though, IoT would surely ruin my day eventually.
For example, in C, you can define a Union type that can hold either a string or an integer, declare a variable of that type and initialize it with a string, and then simply assert that it is an integer.
I think that with your assertion of "valuable in catching bugs" you are referring to Sum Types (often called tagged unions). For Sum Types, if a language supports this concept, it usually also forces you to cover all cases at compile time, whereas with plain unions, you can shoot yourself in the foot, if you're willing to do so.
For example, you can have a List of type List<string>, which would be a list of any length containing any string.
On the other hand, a good tuple implementation (especially a typed one) could allow tuples like (string, integer, boolean), i.e. only arrays of length 3, where the first positions holds a string, the second position holds an integer and the third position holds a boolean. So yes, usually they are represented as arrays, but on a higher level, they are fundamentally different.
As for unions, the parent comment is not referring to the Set operation, he's referring to Union Types.
With this concept, a variable can be one of many types. For example: var input: string | number And at Runtime you would have to find out whether it is a string or a number, to be able to use it.
(Not here arguing whether Dart does or does not have these language features, just trying to clarify this misunderstanding)
As I mentioned, I use milestones the way that you envision epics right now. I group all issues that somehow belong together, for which I want to track progress (and burndown/up over time) in a milestone. The milestone detail view is perfect for this. It has a description, a timeline, start and end date, unstarted, ongoing and finished issues, etc. All they lack to be even more "epic-ish-ly" for me would be a comment thread (as issues and epics have). Essentially, we use milestones as a well-integrade epic-surrogate, while compromising our ability to perfectly track progress on the current sprint (which will probably be resolved soon, with multiple milestone types and multi-assignment).
Also, a way to drag issues into a sprint milestone would be great. (Unless the issue list reflects the priority sorting that is established in the open column of unfiltered boards by dragging issues up and down, then a multi-edit would suffice).
For disclosure, we are a team of ~10 developers working mainly on a single project within a single group. So, switching between the 'group' and 'project' views is not something we do often, since we plan mainly for the project that we work on. So, we barely have visibility of the 'Epics' view in the first place (in fact, when we upgraded to Silver, I didn't even know where to find Epics). I think that I'm also lacking something that screams "CLICK ME TO GET TO THE GROUP THIS PROJECT YOU ARE VIEWING BELONGS TO" other than the breadcrumbs. At least I am _always_ looking at the sidebar first, then using the top navbar (completely ignoring the breadcrumbs, every time)
Anyway, integrating epics with milestones seems difficult. I think a first great step would be to be able to assign a milestone to an epic (i.e. epics belonging to milestones). That could have two immediate effects: The milestone inherits due and start time from epics, and the epics and sub-epics automatically inherit assignment to that milestone. This presumes my view that milestones progress when epics belonging to that milestone progress, and epics progress when sub-epics or issues belonging to that epic progress.
This, combined with the ability to have boards for epics, as I have boards for milestones right now, would probably suffice for me to feel comfortable with using epics at all.
But, I doubt that, even if the aforementioned is implemented, I will get to see the features since I assume they will have Gold-level pressure on infrastructure (they are similar to some of the features that multi-level epics currently implement, and those are gold-level, too).
Since I'm already in the flow: A really funky feature would be boards that are scoped to Milestones. I.e. not boards filtered by Milestones, but boards that belong to a milestone and not to the project. Currently, I have a board for every milestone (our pseudo epics) with our column workflows, and the ritual of creating that could be avoided and made predictable.
In any case, I'm waiting patiently, and observing the gitlab-org epics.
For example, I can create boards that filter by milestone, but I can't create boards that filter by epic. I can't even add epics to milestones. So all in all, with the upcoming feature of assigning issues to multiple milestones, milestones seem like a much better way to group issues than epics.
In addition, with the upcoming feature "Show milestones in roadmap", I barely see any need for Epics, since they integrate so badly with the rest of the planning tools gitlab provides, and I wonder why epics are a thing at all (and why gitlab doesn't just drop epics in favor of a milestone-type called 'epic')
Another feature which I sorely miss, which are admittedly difficult to implement, are swimlanes/rows in issue boards. They would provide an entirely new dimension of possibilities. Relevant Epic in gitlab org: https://gitlab.com/groups/gitlab-org/-/epics/328
All in all, I love using Gitlab, but it also frustrates me greatly, since my main use is for its VCS and planning capabilites, and the latter is in a weird state, which leaves me with no choice but to wait.
Microservices merely ensure that the complexity of using different tools per microservice does not lead to an increase of maintenance burden.
Nonetheless, you still have a maintenance burden if every microservice is built upon different tools and processes, since you cannot address patterns of problems easily that occur within combinations of patterns and processes. The cardinality just increases with every tool and process added into the mix.
This burden of maintenance automatically takes its toll on productivity. Teams will not be able to create, maintain or iterate on code that produces business value (as opposed to managing the platform of microservices itself)
I think there is value in a well defined set of processes and tools because there will eventually be platform concerns that become increasingly difficult otherwise.
I do not have insight in how most companies with successful microservice architectures achieved their success, but I would bet my life that a majority of those companies do not let their engineering teams use tools and processes arbitrarily, unless it serves to REALLY produce value that would be unachievable by the tools and processes used up until that point (for example, because performance is usually sufficient, but a specific service suddenly needs to outperform everything that came so far, so you use C, Go or Rust instead of Python)
I am biased into thinking this because I suspect that most of these companies did either start with monolithic architecture (i.e. supporting multiple languages was impossible or just not feasible enough) or they started with a microservice approach focusing on producing value as quickly as possible after an initial ramp up time. Supporting many different tools and processes from the get go would make the ramp up time longer than necessary.
TL;DR Microservice platform maintenance suffers if tools and processes are chosen freely for each microservice, without any push towards unification.
Oof I need to sleep. Don't mind me, just trying to sort myself out.
I rarely feel this way with Kotlin or Java libs, and I'm only slowly warming up to TypeScript code.
I.e. it would be quickly caught in a review, and the offending developer would have to bring cake the next day.
Yes, TypeScript is not perfect, but we take what we can get
... Sorry, just trying to be funny.
You can do just as badly with an object oriented model as you can with the actor model. Bad applications will be bad.
So the convenient Syntax to define a process is a function declaration. Plus, calling "spawn" to start the process.
Of course, as other responders pointed out, there is also OTP, an established framework (not syntax) to define processes with predefined, battle-tested behaviours.
There is a solution to every perceived problem.
Essentially, they learn from each other, but they will never be quite the same
I didn't get the memo where we decided that we love JSON.