A Philosophy of Software Design
web.stanford.edu
web.stanford.edu
A Philosophy of Software Design – Book Summary and Notes - https://news.ycombinator.com/item?id=31248641 - May 2022 (34 comments)
A Philosophy of Software Design, 2nd Edition - https://news.ycombinator.com/item?id=28975872 - Oct 2021 (1 comment)
Book Review: A Philosophy of Software Design (2020) - https://news.ycombinator.com/item?id=27686818 - June 2021 (61 comments)
Book Review: A Philosophy of Software Design - https://news.ycombinator.com/item?id=18331219 - Oct 2018 (51 comments)
Notes on “A Philosophy of Software Design” - https://news.ycombinator.com/item?id=17906662 - Sept 2018 (32 comments)
[redacted]’s work is also directly influenced by [redacted], as referenced at the end of his article.
For [redacted], I suggest looking at the class website: [redacted]
For [redacted], I suggest his book, [redacted]
I find the "Grug Brain" stuff pretentious and dishonest. "Me not smart. Me like simple things. Me not believe in hype. Hence why me invent complex new frontend framework, and then me hype it up beyond reason."
(To be clear what I'm saying, my point is not that HTMX is overhyped -- it might be, but then so is everything. It's specifically the hypocrisy of the "we're against hypes" hype that makes me cringe.)
agree that anti-intellectualism is a danger if you take grugbrainism too far
It mostly gives you vocabulary and labels and explanations for things that you may already intuitively understand, and teaches you to notice small things that matter. It will probably make it easier for you to discuss and dissect some of the chaos you're already dealing with.
Business and amininistration apps, on the other hand, reflect screwy random-seaming legislation and management whims, which often change in unexpected ways. Management doesn't care that much if their screwy rules and processes complicate automation. (Or don't comprehend the impact.)
I noticed this in debates where SSD experts showed code patterns that assumed too much uniformity between variations of concepts (sub-types, etc.). They just wouldn't fly in biz apps.
I lean toward using flags/tags to manage variations on themes instead of sub-typing, composition, or dependency inversion. Variation granularity has to be small in these domains.
Mind sharing his insights on ways to live?
So tools to manage complexity are welcome in my toolbox.
Some module is "complex" if you need to know more than the interface suggests in order to use that module (e.g. you have to know implementation details); or if the interface requires irrelevant details.
I think there is value in doing a review (specially with junior team members) on their 'design intent' early on, as soon as a prototype/skeleton is up. Proposing a change then is met with a lot less friction.
Today code reviews have become common practice, which is definitely a change for the better, but I rarely see assets like specs or design work reviewed with the same consistency and attention to detail. If anything, the trend has been to minimise formal requirements capture and to reduce or eliminate any kind of up-front design work, as if there is some kind of bizarre dichotomy where the only amounts of time you can invest in these activities before starting to write code are measured in either months or minutes. I believe this is a mistake that often leads to avoidable wasted work and tech debt.
for(int i = 0; i < 100; i++)
{
newList[i] = sourceArray[i];
}
I've also been in working environments where management has insisted that the code reviews be moderated by someone who was a mechanical engineer with no code/software training, background, or experience. I didn't particularly enjoy those....ok, what about if you have code and you think this is not obvious because edge case for browser X version Y therefore I will leave a long comment specifying why it is the way it is and when and under what conditions in the future it should be removed - but the reviewer thinks it is obvious and please remove the comment.
As a general rule reviewers concerns should be addressed, but I have had some experiences in which what the reviewer wanted made the code worse, or even would possibly introduce hard to find bugs.
That actually means that review processes are usually wrong. But then, people experiences are about the wrong process, and that's what they react on.
i had people telling me
d = {i:str(i) for i in range(10)}
was too hard to read, preferring d = {}
for i in range(10):
d[i] = str(i)but anyway, to some senior engineer, the dict comprehension is a chore
“If any part of a system depends on the internals of another part, then complexity increases as the square of the size of the system” — Dan Ingalls
There’s also a DRM-free German translation of the second edition from O'Reilly.
The comment on comments I also disagree with, although that's more contentions. In general I agree with Uncle Bob that comments are usually apologies. Most of the time the code should be refactored to not need comments. Ousterhout does bring up a point that names can sometimes be verbose as a result, but I can't be convinced that's a universal evil in the same way I can't be convinced that comments are a universal evil.
>And, with this approach, developers end up effectively retyping the documentation for a method every time they invoke it!
In what way is that a negative? This is a feature of self documenting code! This is what makes good code so great! This seems like some degree of misunderstanding of Clean Code.
I'm compelled to pick up this book, however.
Can you elaborate on how this is a failure of abstraction? Or maybe what abstraction means to you?
To me, abstraction is about simplify a problem space by making assumptions about the use case.
A hard disk is a bunch of spinning platters that can store 0s and 1s. The drive controller abstracts that by presenting it as if it’s just one continuous stream of 1s and 0s. The operating system abstracts that and presents it as a file system so you can say “shove this data into this name” then later “give me the data in this name”.
The drive controller simplifies the interface by assuming that “where this goes on the platters” doesn’t matter. The operating system simplifies the interface by making many assumptions about where and how we want to organize this data within that stream. This greatly simplifies the use case of… well, basically everything. Except for the things it doesn’t where the abstraction simply no longer works.
All I’ve ever seen “Clean Coder” style short methods do as far as abstraction is reduce it. Instead of a call tree 12 layers deep to finally abstract a problem away as a single operation, people give up halfway through and leave 6 methods that need to be called to do one conceptual thing, meaning the caller needs to understand the underlying implementation/concerns and there’s no longer _any_ abstraction. This isn’t inherent to that approach, but definitely seems encouraged by it.
Shorter methods may (I’d disagree, but understand) help reusability. But whether your `download(string url, string path)` method is a single hundred line method or is composed from parseUrl, resolveDomain, openTcpConnection, sendData, buildHttpRequest, receiveData, receiveHeader, parseHttpResponse, openFile, writeFileData, closeFile, closeTcpConnection… the abstraction is the same if the interface is the same: retrieve a URL over HTTP and write the body to a file. You don’t care about HTTP, sockets, DNS, URL formatting, or anything else.
I would argue that such absolutist rules are harmful. Yeah, there certainly are times when smaller functions are better. But there are times where separating a function into smaller ones does indeed make it 'harder' for me to read, since with each 'abstraction' you're losing context/details that might be very relevant in the code to follow. I would rather have a 40 line function with the dirty low-level details rather than the same split over 50 lines of different functions that I need to go into and figure out the details.
And then again, who is to decide what is 'one abstraction'? Abstractions can be at different levels, and abstracting different things. There really isn't an objective way to do it. I would argue that this is analogous to writing -- there are all kinds of books/stories/poems, short and long etc. and one isn't necessarily better than another.
Indeed. There are millions of us out there developing software for numerous different applications with numerous different trade-offs. “Never say never” is probably good advice here.
I once had a discussion with a prominent member of the ISO C++ standards committee about the idea of labelled break and continue statements of the kind found in various other languages, which let you affect control in an outer loop from within a nested inner one something like this:
outer_label:
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
if (something_interesting_happened) {
respond_to_interesting_thing();
break outer_label;
}
}
}
They were essentially arguing that such a language feature should not be necessary because you should never need deep nesting of loops in a program with good coding style anyway.At that time, I was working on code where a recurring need was to match sometimes quite intricate subgraphs within a large graph structure. This is known as the subgraph isomorphism problem¹ and it’s NP-Complete in the general case, so in practice you rely on heuristics to try to do it as quickly as you can.
That’s a fancy way of saying you write lots of deeply nested loops with lots of guard conditions to exit a particular iteration as quickly as possible if it can’t possibly find the pattern you’re looking for. 5–10 levels of indentation in a function to find matches of a particular subgraph were not unusual. Functions at least 50–100 lines long were common and longer was not rare. It probably broke every rule of thumb the advocates of short functions and shallow nesting have ever written.
To this day, I believe it was probably also the most clear, efficient and maintainable way to write those algorithms in C++ at that time. But it would have been clearer with labelled breaks.
¹ https://en.wikipedia.org/wiki/Subgraph_isomorphism_problem
In software, every named domain can and will grow into its own forest. There was only nginx(or apache) serving html. There wasn't "frontend" and "backend". Nginx served also the analytics. Now they all seem to mean its own thing. There are and always will be manual interacting with the software. What we do is first manually interact, and then write automated script, and then manually interact and make demo video, and then manually interact and make tutorial, and then manually interact and illustrate the user journey, etc. Telemetry is "engineering", analytics is "product". The division goes on forever. Man made concept grows into isolated forest. The more division, hence specialisation, we have, the more gluing we need. People seem to talk more about infinite scaling is a fool's errand. I say so is specialising without seeing the forest first.
I find occasionally zoom into other direction immensely helpful and refreshing.
I started first disagreeing with your point, but I think this last sentences captured what sticked to me. That's similar to the rule of three practice (three strikes and you refactor).
I find it's always hard to keep the whole team aware of the forest, maybe that's why I've seen many premature specialization.
How do we keep a team aware of the forest?
Also, some people are better system thinkers than others, usually more experienced. You need someone to understand everything at a deep enough level to be able to teach it on every team.
It came out at the same time as the GoF book, but I think it is still relevant today and similar in spirit to Ousterhout's book.
The overall pattern really seemed to be “I think we should do X because Y. This falls apart in the face of Z, so don’t do it there.”
That said, it’s been a couple years since I read it so I may be misremembering.
I can almost hear the noise of team members arguing what's important and what's not.
This book is on my list I wanted to read for some time.
I don't think it gets enough credit for keeping its message concise and approachable.
Plenty of nuggets of wisdom in there to glean from.
https://www4.di.uminho.pt/~jno/ps/pdbc.pdf
Rather then using blurry fuzzy concepts about software. This book is called "Program design by calculation".
Which is to view software through the theoretical lens of math, science and engineering rather then "philosophy".
Should software design be interpreted using the blurry and hand wavy concepts of philosophy and literature? or should it be theoretically laid out completely with all primitives formally specified like newtons laws of motion? Can we model software in a very formal way and come to make EXACT statements and conclusions about program design rather then a bunch of opinionated takes?
Unfortunately, like all hard sciences pdbc is much harder to understand then a "philosophy" so most people end up switching majors to philosophy.
Or Perhaps it's not about the challenge... you just prefer the philosophical approach over the theoretical one. Your preference is very valid.
But to you I would ask: can you build a bridge, a car, or an airliner with philosophy? Or do you need hard formal theory and sciences? If we don't have hard and formal theory about software design are we being limited in what we can build?
I'd argue not.
Software design, in my opinion, is both a science and an art so my stance is that we need both the formal theory and science as well as the philosophy and that they shouldn't be viewed as mutually exclusive.
What formal theory have you ever used for designing your software? I would argue you've never used anything. Every abstraction you've ever made was likely a gut feeling, an instinct or following some vague hand wavy rule of thumb.
At best we use type theory for type correctness and complexity theory to calculate efficiency. That's basically as far as it goes with "theory" and these two things aren't even about "software design".
Software design in practice as most engineers use it today is, practically speaking (key phrase), 100% art. Sometimes people come up with big fancy words like "dependency injection" or stupid Acronyms like SOLID to create the illusion of formal theory, but these things are nothing of the sort. It's just tips and tricks.
The plane, the car, the bridge? Those things use both design and formal theory... software design as most engineers use it, again, does not use ANY formal theory, it's almost just purely design all the way down.
Because I think it's really the last one. There is no formula to design a bridge: you design the bridge, and then use formulas and lookup tables to validate it is strong enough. Same for pretty much anything else produced by any engineering discipline.
So in that sense, engineering and programming aren't all that far apart: both start from past experience, and use various validation methods after a design has been proposed, iterating through designs to reach an optimal state. Software engineering, being a younger discipline, is still working on validation methods, and many practitioners find they simply have no budget to apply them (nor any life-or-death constraints that force them to). That's ok though. If you design a new can opener you aren't going through all the processes that apply to an airliner either.
If you read more carefully. What I am saying is that in software engineering, there is no theory. It's all Design. All made up. There's also no verification of the design itself.
I think this is mostly a philosophical statement, but it certainly has truth to it.
Code reviews / rework tackle mostly the code, but not the fundamental design. However the execution of the code tackles the design as well:
- If the design is wrong, the result is bad, that is detected at the execution phase.
- If the design is suboptimal (hard to maintain or extend, bad cpu load, hard to reuse...), well that is usually not solved. IMO that matches your point.
It's fact. What theory is there to prove that the following design is the best possible design? What does "best" even mean? We can't verify formally in anyway how good a design is overall.
We can verify, efficiency, we can verify speed, and we can verify correctness. But design? We can't verify that.
We've defined it for algorithmic complexity. Turns out it's two metrics.. speed and memory. Best means the lowest N, with primitives being algorithmic loops.
What are the primitive modules used in program organization? Given 3 of the smallest possible primitive modules we can define in computing and all the ways possible to compose those three modules. What composition would be best? What is the metric that fits most well with our notion of best? There may be several metrics here. These questions are the ones that are asked when formalizing a theory derived from intuition.
For the bridge it's likely balancing several metrics we already know. Safety, cost, length, etc. Once those metrics are quantified a theory exists to find the best. It's called optimization theory.
Design comes first, always, whether it is for real-world items or for software. The design is then validated using formal methods, and iterated until it meets the required goal.
If you still want to maintain your position that you can compute a bridge, feel free to point out a source that describes the formula for bridges. Or any object that takes significant engineering, really.
What goes on today is largely just a bunch of templates. See the requirements and pick a template and modify it accordingly. That template can definitely be plugged into a optimization equation.
ML models can be used to find the best templates if you want. It's a way to use compute to "design" things and sort of estimates the most optimal design given a set of other templates. These things can be modelled but sometimes they are not computationally tractable to find the best of the best optimal system.
>Design comes first, always, whether it is for real-world items or for software. The design is then validated using formal methods, and iterated until it meets the required goal.
The difference between software and real world engineering is that in software the primitives are well defined and few. You aren't dealing with thousands of variables so you don't need something like optimization theory or ML to estimate the optimum.
There can very much be a theory for software that is practical because software is basically trying to simulate mathematics. It's not so complicated that it can't be done.
>If you still want to maintain your position that you can compute a bridge, feel free to point out a source that describes the formula for bridges. Or any object that takes significant engineering, really.
I maintain that one exists. We just don't know it and may never know it because the theory would involve billions of primitives. I maintain that one exists for software design and while we don't know it right now I think it's possible to find one.
What I don't like about this question is the subtle sass of "maintaining your position to compute a bridge". It's a bit rude. Feel free to not be rude. thank you.
Things like user-friendliness can be "philosophical". You can separately and selectively apply theory and design where applicable, but they cannot in actuality be unionized in some unholy grafting.
I would say for the topic at hand; Of how to organize and abstract your code, if we ever find a complete formal theory for that, much of design will go out the window and what's left is mostly a calculation.
There's no room for design in finding the shortest distance between two points, but there is room for design in picking which points you wish to find the distance on -- I think perhaps for meaningful discussion on this specific topic my definition of "Software Design" is too broad-scope ;)
How do I pick the point such that it minimizes a specification constraint? Let's say that constraint is the shortest distance. This is design by calculation.
Then design is out of the equation. But if the specification constrains is "The two points most pleasing to the user" Then you can "design" those points.
If I had access to every neuron and had a exact fully realized mathematical model of the general human brain, even this constraint of "pleasing" and "usability", in theory could be met with a calculation.
Largely anything that leans more towards "design" means we don't know shit about what's going on so we hire philosophers and artists to make wild guesses. That is essentially what design is: a wild guess.
The more of software we can model in a theory, the less wild guesses we need.
I'm basically talking about "philosophy" the way the book uses the word. Which in short is just the authors opinionated take on software masquerading as something a bit more "official" then just an opinion. I mean would you call your own opinions on software design a "philosophy"?
We should not merge GOF design patterns and SOLID or any other made up "software religion" with a formal theory.
That's what I mean by "belief"
Given ten different calculuses with completely different syntaxes and modes of expression, (for example lamba calculus, combinatory calculus, a Turing machine, a type inference calculus, euclidean geometry, ultrafinitism), each and every one of these ought to be able to express a formal theory that is equivalent. When you are writing software based upon some theory, which calculus will you use to express it? A giant tree of lambdas? A state machine? Pure functions? Mathematically they are all proven to be equivalent so you must make a practical decision based on which one that you believe is best for the job. How will you make that decision? Most likely you will follow some set of personal heuristics that in your experience have shown one form of expression is easier for you than others. And thus you are adopting some philosophy of software even if you try tell yourself that you aren't.
As of right now we don't have a theory that encompasses the best way to abstract and organize primitives.
I'm saying at least use A theory. Any theory. The book pdbc contains a theory and one that from what I've seen comes closest to program design via calculation.
Basically that book is, in short, about functional programming or the lambda calculus way to do things... this is better because it allows you to more exploit the power of math and algebra which are basically the basis for which we developed all of our other formal theoretical concepts.
It's those design choices that are subject to all of the dilemmas that necessitate schools of thought such as those in "A Philosophy of Software Design". The mathematics hasn't been invented yet to determined the most efficient way to lay out complex software. And it won't be until long after our jobs are all replaced by fuzzy AI. Until then, software development is a performance art subject to many different schools of thought or philosophies of design, and you're fooling yourself if you think that you can escape from them.
At the end of the day, there is no mathematical formula to choose which color the border of a selected text-input should be: Only conventions, design philosophies, tastes and opinions.
The book you've linked (although I haven't read it all yet), provides a design philosophy for approaching a subset of the problems that computer programmers face. But: It doesn't have any writing on the hardest problems that programmers face in regards to IO and managing persistent state in a concurrent-access environment.
The philosophy of design doesn't talk about theory at all. It is an opinion on the most efficient way to do things not a proof.
If there was a theory, the answer on the "best" way would be a proof. The answer is indisputable given the axioms.
>At the end of the day, there is no mathematical formula to choose which color the border of a selected text-input should be: Only conventions, design philosophies, tastes and opinions.
And that's why the color of the border is not technically part of software engineering. They call that department the art department or the graphic design department. And the people who work this stuff are called "designers"
>The book you've linked (although I haven't read it all yet), provides a design philosophy for approaching a subset of the problems that computer programmers face. But: It doesn't have any writing on the hardest problems that programmers face in regards to IO and managing persistent state in a concurrent-access environment.
No it doesn't provide a philosophy. It provides a theory based on axioms. The choice of the axioms and the resulting theory may be done using "philosophy" but the outcome of that choice is a formal theory.
>The book you've linked (although I haven't read it all yet), provides a design philosophy for approaching a subset of the problems that computer programmers face. But: It doesn't have any writing on the hardest problems that programmers face in regards to IO and managing persistent state in a concurrent-access environment.
There's a short chapter on monads but your right. I never said there's a complete theory and I hinted and mentioned several times in this overall thread that there is no complete theory.
Even the book is incomplete. It's a draft.
Yeah it was actually progress when the field largely separated the philosophical mumbo jumbo away from the pure math. In the past math text books were littered with this mumbo jumbo because people couldn't separate the philosophy away from the axiomatic logic. Textbooks were just a mess. Nowadays there's a clear delineation. I believe it was Newton who started this separation trend with his laws of motion.
Mathematics is an entirely separate department that is NOT under philosophy in most schools because of this.
Pure math is really nice, but there are so many aspects of human activity where this math is just totally useless. This is where we have to use the fuzzy words and stuff and where rigorous interpretation that you get trained in philosophy and other wordcel departments comes useful.
I really encourage you to engage with some history of philosophy. You'll probably enjoy it and maybe change some of your views. Maybe try some history of science?
Personally though because philosophy encompasses stuff like animism I don't give the entire field much weight. Aspects of it are interesting but the entire field as a whole is a category error that encompasses everything on the face of the earth. What is not philosophy? I mean it sounds like philosophy is the study of anything and everything.
Anyway to your point physics supposedly is a mathematical model that can model everything down to the tiniest atom. There are holes where not everything can be calculated in a closed form equation and there are holes where the fundamental primitive is true randomness which is something hard to replicate or define.
In this sense physics can model almost (key adjective) everything in the the universe. Including most of all human activity. Because in the end that's of what's going on. Atoms.
Calculate correctness of some business logic, when part of "correctness" is correspondence to some badly-written procedures, and another part is correspondence to some regulations that are spread across ten thousand pages.
Calculate correctness of an OS scheduling algorithm that has to work against a (not precisely known) variety of task mixes.
And so on. There are parts of the requirements that are blurry and hand-wavy. That makes the "calculation" approach hard. At least, you have to translate the hand-wavy stuff into precise things that you can calculate. And you can't calculate that translation process, because the inputs are hand-wavy.
Given a hand wavy blurry specification, well... of course the implementation will be blurry and hand wavy as well.
Pointfree programming allows for theory. It allows for algebraic composition of functions which in turn allows application of algebraic theory.
I mean in the end what is a computer program? A set of functions. Wouldn't you build a program by composing functions together to form bigger functions? It makes sense for this to be the fundamental theory of program organization.
Of course IO and mutation aren't initially included in this theory but that's a different aspect of the theory once you get more advanced.
So basically you're just saying something along the lines that in your opinion you don't like the theory of algebra or geometry or some such. It's not invalid, but like the philosophy book, just another opinionated take.
While a program in practice can have "points" an algebra of functions should be a theory like number theory. Number theory deals with numbers only, function theory deals with functions only.
I'm not so strict on this in practice, the function must eventually be called and in the end the compositions converge into a point. But if you want to apply algebraic theory to the functions, they need to be point free.
Number theory is not just numbers, by the way. It has plenty of functions as well, for example the Riemann zeta function.
The basis of all formal theories includes logic. I haven't heard of any illogical formal theories. Logic isn't just algebra it's everything.
I acknowledge there are other interesting primitives other than functions. But does it make sense to formulate a theory with linked lists and dependency injection as it's core primitives? Then we build everything else in terms of those two concepts? Seems arbitrary. More than likely there are more fundamental building blocks we can use to develop a theory.
If we want to make a theory of computation what is the core primitive that computes? A function. So it makes sense to use this as the core primitive of a theory.
>Number theory is not just numbers, by the way. It has plenty of functions as well, for example the Riemann zeta function.
How should I put this. In number theory you have numbers as an instantiated primitive. Then you have rules on how to compose those numbers to form other numbers. Those rules are called "functions".
If we have a "function theory" on computation. Then the instantiated primitive is a function. Then we need rules on how to compose those functions to form other functions. Those rules are called "functions".
Note the repetition of the two paragraphs above. It might clarify to you what I'm talking about. So in a sense the word "function" in the second paragraph is more Meta... a function of functions.
Anyway the point here is that we want to formulate a theory with the lowest amount of primitives and axiomatic concepts.
A theory makes only sense with respect to some logic. So first, you need to define what logic you are using. This logic is your theory with the lowest amount of primitives and axiomatic concepts.
Now, once you have that, you can turn your attention to other things on top of that. If you are interested in functions only, sure. You can for example study the lambda calculus.
But don't pretend that this is so that you can reason about computer programs better. Sure, learning more about functions is useful, but numbers are also very important for computer programs. So are trees. And graphs. Expressing all of these just in terms of functions can be a fun exercise (pun intended, Church numerals anyone?). But instead of trying to express the important concepts of your program as functions, and then studying them, maybe your time is better spent studying the concepts themselves directly.
Logic as I know it can't be made up. It's already well defined and the basis for all other formal theories.
The lowest amount of primitives and axiomatic concepts is largely a design choice for developing a theory. Makes it easier to deal with the theory rather than a theory that starts out with extremely complicated axioms.
>But don't pretend that this is so that you can reason about computer programs better. Sure, learning more about functions is useful, but numbers are also very important for computer programs. So are trees. And graphs. Expressing all of these just in terms of functions can be a fun exercise (pun intended, Church numerals anyone?). But instead of trying to express the important concepts of your program as functions, and then studying them, maybe your time is better spent studying the concepts themselves directly.
Yeah but I would want to prune all that other stuff away and focus on a theory on the best way to organize and abstract programs. The primitive most important for that is the function because that's basically at it's core all a computer does, just calculate stuff.
Of course logic can be made up, and in fact, all logics are. First-order logic, simply-typed higher order logic, dependent type theory, all made up.
My favourite made up logic is Abstraction Logic (http://abstractionlogic.com).
But I guess what you mean is that you are a mathematical realist. That's good! I am too.
> Yeah but I would want to prune all that other stuff away and focus on a theory on the best way to organize and abstract programs. The primitive most important for that is the function because that's basically at it's core all a computer does, just calculate stuff.
If that's what you want to do, then that's what you want to do!
That's like saying math is made up. Is it made up or is it discovered?
You're just being pedantic.
>If that's what you want to do, then that's what you want to do!
Yeah and if you want some theory of program design that encompasses every damn concept under the sun as an axiom go for it as well! Genius!
Personally, I think it is discovered, although the concrete incarnations are made up, of course. That's pretty much what it means to be a mathematical realist.
> You're just being pedantic.
I just know more about these things than you seem to do. People disagree on what the "right" logic is (personally, I think the right logic is Abstraction Logic), and the choice of your logic influences your axioms. First-order logic for example has no built-in functions as mathematical objects, so you need to come up with axioms for functions. Simply-typed higher-order logic, on the other hand, comes fully equipped with functions, so no need for additional function axioms. And also no need for additional axioms for other things, you can create numbers, trees, graphs etc. without introducing new axioms (except an axiom for an infinite type of individuals) for these things.
When I look at the book you cited, it's just full of really simple stuff made really complicated. Pointless, indeed. Personally, I am more interested in the opposite direction. But that's just my personal opinion.
No you're being pedantic. I don't think you know more.
Think about it. We both agree math is discovered. So why the hell are we diving into this tangent? It's because you decided to say that logic is made up and then subsequently agree it's not. The nuance of whether and what part of logic is made up is pedantic.
>When I look at the book you cited, it's just full of really simple stuff made really complicated. Pointless, indeed. Personally, I am more interested in the opposite direction. But that's just my personal opinion.
Sure tbh I never fully read the book. Skimmed. Seems to be a good resource for beginners. But I also don't think you're an expert.
Your interested in the opposite? You mean the philosophy of programming? Well good on you. You go study that then. Again I can't understand your genius.