16 ms·
Imperative configs are out; Declarative configs are in
- rgovostes 4y agoAs a university student discovering constraint solvers like Z3, I believed that the future of computing was declarative programming, with black box solvers that would obviate the need for specialized algorithms. Dealing with Webpack cured me of the idea that declarative is strictly superior. Configuring it is just endlessly consulting the documentation, and then the underlying code, and then cargo culting StackOverflow answers to coerce the black box to create the output I want.
- thenipper 4y agoThere is a ton of interesting work being done with solvers adjacent to machine learning. I just finished a job where I was working with an operations research team solving inventory placement and transportation
- btown 4y agoDeclarative is great if there is always one path to get to where you're going. But I like to use the example of a Git repository where you've renamed and also changed some parts of a file. You commit the new state - was it a deletion and a brand new file, or a migration and modification of an existing resource? It's usually a non-issue because Git is smart, and files don't really care about their identity - but what if this was a database server and you need control over what happens when, and how things drain? Do you trust the system to choose the right path vs. "delete the database and make a new one?" At some point you'll need imperative thinking to make sure your bases are covered, even if that is "we have a 3 phase rollout plan for different versions of the declarative config." And that's perfectly fine, in many cases. But it's important to never get into a cargo-cult level of "if it can't be done with one declarative change it shouldn't be done" - because then you'll either get stuck or light things on fire.
- alajmo 4y ago> The config has now more than doubled in line count, making it impossible to remember the original intent of the configuration. Not really, I found it quite self-explanatory.
- 8jy89hui 4y agoComplicated static configs are out; Scripts as configs (like Neovim) are in. Both of these examples seem like they would be better fit with Lua-based configs. Scripts as configs give incredible amounts of power to the user without the programmer having to specify everything the user might want to do.
- lamontcg 4y agoIf they pull in dependencies that can make them very non-portable, while that is typically where all their power comes from over normal config files.
- rcarr 4y agoMy two cents on the declarative vs imperative debate: Yes all code is eventually imperative if you go down low enough. But your code should be as declarative as possible for your user. For example, the business department write a ticket for me to build a new feature. They essentially declare some functionality. I then take the imperative steps to code that on the front or back end. To do this, I will likely need to use some tooling. As far as the tooling is concerned, I am now the user/business department, I declare what I want in the tooling and the tooling should make it for me. The developers of the tooling then write imperative code to handle that. Maybe they rely on tooling to do so, in which case they become the user and so on. The cycle repeats itself recursively until it reaches the machine code at the bottom. You could even take it further if you like in that the hardware engineers behind the processors are now the developers carrying out the imperative functionality who in turn carry out their job using electronic measuring tools which makes them users etc. Basically, everything should be declarative by default for the intended user of the application unless they have specifically requested finer grained control. The user has enough to deal with getting their particular task done, they shouldn’t have to navigate between layers building the tools that they need to get their job done. Unless he’s working on something unique that requires it, the tradesman doesn’t want to go to the DIY store and give them instructions to build a drill, he just wants to buy a drill that meets his requirements so he can get on with his job.
- est 4y agoAhh yes, the old stuff is new again. Ansible.
- mbrodersen 4y agoDeclarative: Specify the result you want. Imperative: Specify (step by step) how to get the result you want. Examples: Declarative: I want a PC with the following code installed: X, Y and Z. Imperative: First upgrade X, then install Y, then uninstall W, then install Y and Z.
- ayf 4y agoA good overview of why legacy CD systems cause so much pain in cloud-native environments
- andybak 4y agoThis is an old debate surely? My first awareness of it was probably related to Django's settings.py back around 2007 but I got the feeling from discussions then that it was a discussion that had been bouncing around for a long time before that. The counter-argument is that declarative configs inevevitably sprout programming-like features - and if they don't someone will write code to generate them. (disclaimer - in true HN fashion I haven't properly RTFA'd - dinner is nearly ready and I'm feeling bold)
- naphatkrit 4y agoYep the idea of declarative winning out over imperative is nothing new. Yet for some reason, most deployment systems make you go through an imperative flow if you want to orchestrate releases.
- taeric 4y agoBecause "burn it all down and rebuild everything" is by far the easiest orchestration to create from a declarative config. And is almost certainly not what any technician is going to want to happen to their production system.
- scubbo 4y agoSort-of a nitpick, but for stateless services that's _precisely_ what you want to happen!
- taeric 4y agoNot when your infrastructure includes your data store, though. Or if it includes such things as your application endpoint. You may want to stand up the new endpoints and then drain over traffic, as an example. Not take an outage for a deployment.
- tremon 4y agoNot when your infrastructure includes your data store, though Then the service is no longer stateless.
- taeric 4y agoI.... don't buy the initial example. Google maps is still an imperative list of directions. It just keeps track of the current pointer for you, and is able to reroute. If anything, that is an example that a dynamic action plan is more adaptable than a static one. That said, declarative clearly has advantages when it can work. You probably still want a "break glass" way to see what the actual steps that will be taken are, but can get surprisingly far without that.
- naphatkrit 4y agoOh totally that declarative can and will often compile down to imperative. The question is what do you ask the user for? My take is Google maps is declarative in the sense that you ask for your destination, your constraints (e.g. no highway), and time to leave, and it dynamically generates the underlying imperative steps like you said (but continuously adapt if you go off course, which you cannot do unless the initial input was declarative).
- taeric 4y agoThat example still feels off. The "offline printout" was done in a very declarative way. It is just fixed on the execution plan. (And, quite frankly, less obnoxious to me if I decide to stop and get gas or food.) You can even prepare alternative routes ahead of time, if you want to speculate on conditions. Is a good idea to role play some of that ahead of the time, in any case.
- naphatkrit 4y agoThat makes sense. I'm not necessarily arguing for continuous intelligence in this post, just that declarative configs enable it. Even the initial conversion of a destination to a set of directions is a compilation of declarative to imperative. Imagine if Google Maps was truly imperative and asks you to input the individual roads you want ahead of time - then it would not be useful.
- taeric 4y ago
- deleted 4y ago[deleted]
- 0xbadcafebee 4y ago"My dad switched from working with a map printout without knowing real-time conditions, the imperative flow, to Google Maps with turn-by-turn directions, the declarative flow." There is no such thing as an imperative or declarative "flow". By its very definition, declarative does not have "flow". It is just a statement. Imperative (in programming) literally means "describing steps that change state". Declarative (in programming) literally means "describing a state which is desired". Declarative would be "I want a cheeseburger." Imperative would be "Get me a bun, and some lettuce, and tomato, and mayo, and raw meat. Cook the meat on a grill at high heat, flipping half way. Put the mayo on the bottom of the bun, then the meat, then the lettuce, then the tomato, then put on the top of the bun. Give it to me." It's still strange to me how people learn about "magic words" like declarative and imperative, and then try to ssstttrrreeeeettttttcccccccchhhhhhhhhhh their meaning into some new paradigm that they have just thought up. There is no such thing as an imperative configuration file. A configuration file describes how a program should be configured. Even when the configuration file "describes a series of steps to change state", it's still declarative, because the configuration file is still declaring to the program how to operate. It's the program that is imperative or declarative, depending on how it interprets and acts on the configuration file. (This is made clearer in programs like Ansible, which, within the exact same configuration file, supports both declarative and imperative statements) Before you say "what about template files! jinja2! go templates! hcl!", that is merely a DSL, which is no longer a configuration file; it is effectively a program in a crude programming language, interpreted by an interpreter (the program loading the file). (edit: I agree with the author's point! But I suggest we stop using these terms 'declarative' and 'imperative', and instead say "let's write programs that are functional enough that we don't need to write configuration files that are mini-programs")
- geuis 4y agoVery good breakdown. Couldn't agree more. Except that mayo should go on top.
- 0xbadcafebee 4y agoI don't disagree, but a lot of burgers end up dry, so the bottom bun stays dry and bland, which makes me sad. Sauce on the bottom solves that, and the top bun gets wet from the tomato. Optimizing for the 80% burger.
- sly010 4y agoThis just looks like a frontend over kubernetes.
- naphatkrit 4y agoNot exactly? Kubernetes natively doesn’t have a solution for pushing across environments afaik.
- moralestapia 4y ago>My dad switched from working with a map printout without knowing real-time conditions, the imperative flow, to Google Maps with turn-by-turn directions, the declarative flow. LOL, he got it backwards, "turn-by-turn directions" is the imperative flow. Can't expect much after reading that.
- phailhaus 4y agoI was thinking the same thing, but his point is that with Google Maps you simply declare your end goal. It figures out how you should get there based on current conditions.
- naphatkrit 4y agoI guess I should have said "voice-guided" turn-by-turn huh? https://www.forbes.com/sites/anthonykosner/2012/12/13/google-maps-returns-to-ios-now-with-voice-guided-turn-by-turn-navigation/ https://www.forbes.com/sites/anthonykosner/2012/12/13/google... is what i was referring to :)
- moralestapia 4y agoHuh? Voice or not, it's still imperative. :grimacing:
- phailhaus 4y ago"Declarative" and "imperative" are relative to the goal you are trying to achieve. If your goal is only to reach your destination within some parameters, then writing down every single step to get there is imperative. The declarative approach is to specify the destination and those parameters, and allow the engine to determine how to get there.
- saltcured 4y agoRight, imperative directions would be the turn by turn recipe to get from A to B. Declarative directions would be "be at B". Route planning is the solution method to convert from declarative to imperative navigation directions. Of course, it's also a nuanced value judgement. The declarative/imperative abstraction is almost fractal, as we could consider a trip with multiple intermediate destinations as either a declarative itinerary or an imperative plan. Or we could go further and talk about all the control steps it takes to "turn right in 100 meters". What the article describes for the father's driving is the difference between ahead-of-time and just-in-time navigation. It's not a very good metaphor for declarative versus imperative configuration management. To turn it into one would make for a perverse story, i.e. telling the father where you want to meet versus telling the father a long list of turns starting from the airport while obfuscating the destination.
- kazinator 4y ago> If a pipeline fails halfway, most CD systems don’t have the ability to retry. The only option is to restart a pipeline from the very beginning. Now with declarative configs, an intelligent delivery system, the system will detect that staging is already on the desired version and skip that push, allowing you to deliver value to your customers faster. Hey, an interrupted "make" can always restarted from where it left off without ever having to do a "make clean", so what could go wrong.
- zmgsabst 4y agoThis example is backwards: Showing a map printout while ignoring runtime state is declarative; executing directions step by step, adapted to the present state of the system, is imperative. I’ll set aside my feelings about stretching meaning to say — if you are going to use technical words this way, don’t use them backwards.
- shkkmo 4y agoDeclarative works better than imperative only when someone has already defined the imperative process that takes you from any given state to your goal and does that for you based on your declaration. Google maps works great for a set of origins to a set of departures for certain modes of travel. Once you get outside those bounds, it can fail in significant ways. Thus the entire premise of the article thus seems to boil down to: If someone has already done the work, don't re-do it. The problem with declarative configuration is that as the systems they manage become more complex, inevitably you leave the bounds of the solved problem and have to start solving it for yourself imperatively.
- righttoolforjob 4y agoThis is the correct answer. You can declare only when someone else already has performed the imperative chore, i.e. written the source code, programmed. Q.E.D.
- Jtsummers 4y ago> Declarative works better than imperative only when someone has already defined the imperative process that takes you from any given state to your goal and does that for you based on your declaration. [emphasis added] No, someone (as in a person) doesn't have to define the imperative process, that would be stupid. We have computers to compute things, including computing new processes. Oracle didn't hire a bunch of human query planners to manually construct every query plan, they made a query planner. Google didn't sit down a nation of navigators to plan out every route, they wrote a program (or likely a set of programs) that computes it on the fly.
- shkkmo 4y ago> they wrote a program (or likely a set of programs) that computes it on the fly. Which is precisely the sort of imperative process I am referrencing...
- deleted 4y ago[deleted]
- pmarreck 4y agoAs a recent NixOS convert, I concur
- bastardoperator 4y agoYou might end up with the nightmare config they highlighted if the person writing the config has no semblance of DRY, but it's unlikely someone versed in CD systems isn't going to use techniques afforded to them for reducing boilerplate.
- tremon 4y agoThe irony is that many declarative systems have very poor support for symbols, templates, and code reusability in general, so declarative configurations carry more boilerplate than imperative configurations.
- otikik 4y agoHey author: your css seems off on mobile. Text reads fine, but code looks tiny in comparison