philosophy -- Berry Web Blog -- page 0

Criteria for Software Freedom

Posted: 2016-03-15. Modified: 2017-08-01. Tags: Opinion, philosophy, programming.

“Free software” means software that respects users' freedom and community. Roughly, it means that the users have the freedom to run, copy, distribute, study, change and improve the software. Thus, “free software” is a matter of liberty, not price

Free Software Foundation

1 Introduction

The FSF's definition of free software, written above, is a useful broad principle which relates to how much control a human user has over a given computer program. In this article, I discuss some specific criteria which we can use to assess "Software Freedom".

I think the typical definition which people think of when they think "free software" is simply whether the software is open-source, or perhaps even if the software costs nothing to use. However, while these users are correct for some definition of "free software", I, like the FSF, think it can be useful to load the term "Free Software" with more implications in order to better capture the nature of the relationship of a human user to a piece of software. What is important is not really what the legal status of a piece of code is, but rather the practical level of control which a user has over that code. In this era of ever-increasing computer technology, I think it becomes more and more important that humans can control the computations which they use, and not the other way around.

I propose three criteria which I think are especially relevant today in our age of cloud services and increasingly complex software. My goal is to assess the level of control of the human user over a piece of software which she uses. The first criterion is simply the basic definition of open-source, the second criterion is mostly implied by Stallman's definition of "Free Software", and the second definition is not so directly implied. My criteria are:

  • Availability of source-code.
  • Control over deployment
  • Accessibility to understanding.

2 Availability of source-code

This criterion is probably what most people when they think of "free software" or "open-source software". Whether a piece of software is run remotely or locally, having access to the source-code can provide a user great insight into what a piece of software is actually doing. Availability of source-code often corresponds to the user having greater "control over deployment". This criterion is the one which is addressed by the various open-source software licenses.

3 Control over Deployment

Control over deployment is a basic precondition to control over computation. If the computer user cannot control when an application starts, stops, and is modified, then the user cannot say that he controls the computation which is being done. Many of today's cloud web-apps run afoul of this criterion – not only are most of them closed-source and closed-data, but they can and will be discontinued when the provider decides without recourse for the user. Cloud services are discontinued all the time – see this page or this page for some examples.

I define three levels of "control over deployment":

  1. The user does not run the software, and does not have access to enough information about the infrastructure, source, and data of the project to "fork" the deployment of the software to run it herself.
  2. The user does not actually run the software on her computer, but if the service is ever discontinued or negatively modified the user has enough information to "fork" the deployment of the software and run it herself.
  3. The user controls execution of the software herself.

Level 0 is the default level of control over most web-apps. Google Translate is an example of a service I classify at this level. If Translate is ever discontinued, I have no ability to bring it back. I do not have access to the source code for google translate, and cannot know much about the infrastructure or methodology used to run it. Google Translate is a useful service, but it would be so much more useful to me, a hacker, if I could spin up my own version of "Translate" with my own changes.

Level 1 is the level of control afforded by most hosted open-source software installations. Sage Cloud is an example of a service in this category. While Sage Cloud is an online service for which I do not directly control deployment, Sage itself is open-source software, and I can easily spin up my own "Sage" server with most features intact. Level 1 has many benefits over Level 0 for interested computer-users, not least among them that the user can study the implementation of the service to potentially improve it and change it to match his own purposes.

Level 2 is the strongest level of control over computation. In Level 2, the user controls the computer on which the software runs, and can choose how it is used and when it is upgraded. Level 2 is the level corresponding to traditional desktop software. Even closed-source software provides a fair amount of control to users when it is run locally – the user has a perpetual ability to run the software, and the service cannot be removed without recourse. Additionally, the user can potentially reverse engineer and/or add extensions to even closed-source software as long as he has access to the binary.

Level 2 is obviously stronger than Level 1, but I think the Level 1 is still an important step over the default zero control level of typical cloud services.

4 Accessibility to Understanding

Accessibility to understanding is another criterion which has important implications for the practical level of control of humans over their computers.

Consider a large piece of computer software whose source is distributed in machine code, without comments, under the GPL. Technically, it is open source. If you run a disassembler on it you can get assembly code, and change it to your liking. While the software may be open-source, it will likely take you a very long time to figure out how the software works and modify it to match your own goals. Therefore, your practical level of control over the software is much smaller than it could be if you had access to the source code in a high-level language. Here we see that it is not merely the legal status of the source of a piece of software which determines your control over it, but also the technical status of that source.

One side-effect of the "Accessibility to Understanding" principle is that it sometimes indicates that, indeed, "worse" can be "better" for humans. If you are confronted with a 1-million line program which has marginally better performance at some problem than a 1000 line program, if you are like me you will probably opt to use and hack on the 1000 line program.

5 Conclusion

In this article, I discussed three criteria which I think are useful for assessing how much control a user has over a piece of software. The first condition is plainly evident to most people, but I think the other two criteria are less talked about and used.


Fundamental Principles in Writing Computer Code

Posted: 2016-01-25. Modified: 2016-01-25. Tags: programming, Opinion, philosophy.

1 Introduction

There are a huge variety of programming languages out there, an infinite number of concepts, and numerous ways to think about any given problem. How can one logically discriminate among these choices to make wise programming decisions?

First off, there exist a number of software-design camps, each with their own design methodoligies and folk-loreish guidelines.

Some people claim that you should thoroughly document your code with comments, others claim that you should use comments sparsely lest they become out of date and misdirect future readers.

Most people think it's important that programmers "write understandable code." But how does one define what is understandable and what is not? Is it better for code to be concise and dense (ala APL) or verbose and wordy (ala COBOL)? Some people argue that verbose code is easier to understand, as it can sometimes be "self-documenting", while others claim that dense code is easier to read, as it is shorter.

Object Oriented designers love applying acronyms such as SOLID and GRASP to software. Functional designers love applying principles and techniques such as immutability, declarativity, currying, and higher-order functions.

Every programmer has a preference for a certain programming language – probably the one which she has spent the most time with. People get into passionate debates comparing languages and software ecosystems.

Almost all programmers seem to have internalized the concept of "code smell" – we say things like "that code doesn't seem quite right" and "in Java, it's best practice to implement that feature differently".

2 What are the Objective Criteria?

All of the above statements, standing on their own, are subjective in nature. Is there a provable basis for any opinion with regards to software design?

My answer is that there are a number of objective mathematical criteria which affect software design, but that actually applying these criteria to real world problems involves making subjective judgements, just as everything in the real world involves making subjective judgements.

Below are some core objective principles which can be used to assess the runtime quality of software relative to criteria. The runtime principles are commonly discussed, I do not think my sourcecode principle is commonly expressed, in the form I express it at least.

3 Runtime Principles

3.1 Correctness

This principle is, essentially tautologically, the most important principle w.r.t software implementation.

Given a set of goals G, I define correctness for an algorithm A as whether or not A successfully produces the right output and invokes the correct side effects to satisfy G. There can be subjectivity in creating and assessing the goals. Undecidability is a potential choking point for many algorithms, and must be handled in the definition of G.

3.2 Runtime Guarantees

My definition of this principle is different than my definition of correctness, in that, rather than assessing merely whether the correct output/side effects are produced within standard execution of the code, we are also assessing guarantees and/or probabilities of runtime "performance" in the areas of reliability, space, and time usage.

Examples of features which I would categorize under this feature include uptime probability guarantees, fault-tolerance, bounded response time guarantees, and bounded space usage guarantees.

I do not include "runtime computational complexity" (asymptotic measures of how the performance of an algorithm changes as the size of its input changes) in my definition of "Runtime Guarantees".

3.3 Runtime Complexity

"Complexity" in various forms is a core topic of Computer-Science curricula, and is extensively discussed and researched. In computer science, we typically consider runtime time complexity and space complexity as primary criteria of the quality of an algorithm. One can also consider concepts such as runtime "energy complexity" as a loose concept defining bounds on likely energy usage.

4 Sourcecode Principles

Each of the above principles has been extensively discussed in academic and engineering literature. However, notice that NONE of the principles above say anything about how we should organize or write our code. Below I put forward a principle which I think is the core principle affecting code organization and writing.

4.1 Occam's Razor – Minimum Description Length

4.1.1 Introduction

Occam's Razor has time and time again shown its power in choosing models to explain phenomena. It can be shown to be naturally emergent in a wide range of fields including Bayesian probability, natural philosophy, and Theology.

Occam's Razor is simply the statement that "the simplest explanation is most likely to be the best."

4.1.2 Justification

The most convincing mathematical argument for Occam's Razor which I have seen comes an analysis (link to Chapter 28 of "Information Theory, Inference and Learning Algorithms" by David Mackaye) in Bayesian probability which concludes that "simpler" explanations in a given explanation-space have higher posterior probability after any given observation.

4.1.3 Bridge to Software

But how does Occam's Razor apply to software development? After all, its commonly stated purpose is in model selection.

I think the bridge from Occam's Razor for model selection to Occam's Razor for code organization is recognizing that choosing among code organization options is a form of model selection.

The phenomena we are trying to explain (match) are the runtime requirements of the software system. The models are the different code layouts and structures which we can choose among.

Software development is about solving problems with computers. Therefore, we can view the program as a model estimating the desired solution to the underlying problem. If two models (programs) perform roughly the same function, then we can choose between them by the one which more "sharply" models the problem, e.g. the one which is shorter by the principle of Occam's razor.

4.1.4 Application

If you agree that Occam's Razor is a reasonable principle to direct code composition, and even perhaps that it encompasses such commonly uses principles such as DRY (don't repeat yourself) and YAGNI (you ain't gonna need it), then the next question is: how can we apply Occam's Razor to make code organization choices?

Applying the principle, of course, is where we run into some trouble and must deal with subjectivity. In order to apply Occam's Razor to software, I propose that we look at Occam's Razor from a slightly different perspective which is often used in machine learning and statistics. Let's make more exact what we mean by "simpler" and instead discuss "minimum description length".

To compare two pieces of code with the same functionality, we can usually say that the code which has a smaller minimum description length more sharply models the desired feature set.

How shall we compare description length. Shall we compare lines of code? Bytes? Number of tokens? Function points?

I think each of the above approaches can be useful, but for most applications number of bytes or number of lines should be relatively interchangeable, when used together with common-sense.

Another alternative, which may be more useful to compare programs written in different languages or with different style conventions, is to compress the text of the program and compare the compressed size. This gets us closer to the "minimum description length" of the program and helps elminate differences caused by whitespace, descriptive variable names, and the like.

5 Conclusion

In this paper, we discussed a number of principles for writing software which are objective in their core nature and are based in mathematics. We discussed the standard principles which can be used to assess a program's runtime characterestics. In addition to those, however, we also discussed how the "Minimum Description Length Principle" can be used to make choices about code organization and design. Not only does the "Minimum Description Length Principle" encompass other commonly used principles such as "DRY" and "YAGNI", but it also provides a general framework to assess the "sharpness" of a codebase's match to a given problem. For each of the principles we discussed, we touched on the various difficulties in applying it to real-world problems.

While the principles discussed in this paper do not change the subjective nature of software development, they do correspond to core features of a software program that can be measured objectively or pseudo-objectively, and that can be strongly supported by simple arguments in mathematics and philosophy.


Prognostication vs Software Development: Subjectivity and Complexity

Posted: 2016-01-25. Modified: 2016-01-25. Tags: Opinion, programming, philosophy.

"Crede, ut intelligas" – "Believe that you may understand"

– Saint Augustine, Sermon 43.7

As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality.

– Albert Einstein, Geometry and Experience

1 Uncertainty in Life

Underlying every experience in life is uncertainty. It is in general impossible to obtain complete confidence about anything.

When a human walks through a room, she can instantly filter out irrelevant details. The reason that she can filter out irrelevant details is that we as humans subconsciously accept certain truths and foundational beliefs. Without making these operational assumptions, we would have to consider an untold number of possibilities at any given point in time and we would not be able to function in the real world.

Examples of details which we safely disgard include:

  1. The ceiling is not going to fall on me, I do not need to analyze its structural integrity.
  2. The pattern of light on the wall is still, therefore it is unlikely that it is a threat to me but rather is just light shining through the window.
  3. The laws of gravity, force, and momentum will continue to stay in effect.

Subconsciously accepting these beliefs and many others about how our world functions allows us to focus on important threats and goals, such as

  1. My little sister just stuck out her leg to trip me.

While it is easy for us to filter out extraneous details and sensory inputs as we go about our daily lives, this is by NO MEANS easy for automated systems. Computers, unless they are programmed quite cleverly, are prone to get bogged down in the "combinatorial explosion" of possibilities which real-world inputs and problems tend to create. Computers' difficulty with real-world problems has prompted the creation of a saying known as "Moravec's Paradox":

"it is comparatively easy to make computers exhibit adult level performance on intelligence tests or playing checkers, and difficult or impossible to give them the skills of a one-year-old when it comes to perception and mobility" – Hans Moravec, 1988, Mind Children

Anything which is done following a rigid set of rules can often be automated comparatively easily, while tasks, however simple, which involve subjective perceptions can often strongly resist automation.

2 Uncertainty/Subjectivity in Software Engineering

Most human occupations make use of our ability to navigate ambiguity, and software "engineering" is no exception.

Modern software development is essentially climbing through the apparatus of an immensely complex logical system and making appropriate modifications to produce a desired result. At every step, ambiguity and intuition rears its head. We face ambiguity in our objectives, subjectivity at every implementation step toward meeting those objectives, and immense ambiguity in every interpretation of human communication.

I think that much of "software engineering" is quite subjective. In the design phase of a project, people with different backgrounds and skillsets can often approach the problem with vastly differing methodologies and architectures, but no one methodology can be proven to be "correct". Programmers can often achieve similar results using any several of a variety of programming paradigms, languages, and planning approaches. Whether it is best to design in a functional style with Immutable and Declarative design principles, in Object-Oriented style with SOLID design principles, or a procedural style with close affinity to the hardware, depends on the problem at hand and the prior experience of the programmers. The goals for a project may include hard boundaries such as reliability and performance guarantees, and perhaps runtime-complexity bounds for the behavior of the program, but the organization of the code which gets us to the end-result is in large part a matter of taste and discernment. It all comes down to achieving the desired external behavior in an acceptable amount of time. Regardless of the specific design choices the designer makes, what is critical is that the designer is able to intuitively grasp the problem and the interacting actors which affect implementing the problem, and can swiftly navigate the logic maze towards a workable solution. In other words, a software designer must be able to intuitively navigate complexity as well as subjectivity in order to produce a successful software design.

3 Complexity

If a planner cannot effectively grasp the interacting pieces going into a planned software system, but instead is overwhelmed by the software's complexity, the planner's designs and estimates are likely to be quite poor.

The issue of managing complexity is a bridge from the skillset of software development to the skillset of many other fields, and appears to be a core human mental skill. Just as it is difficult to deliver quality software in a system for which you do not have an effective mental model, it is difficult for people to deliver any reasonable insight on real-world systems for which they do not have an effective mental model.

The classic case of a system which is too complex for people to gain reasonable insight on in general is… any system for which a person is trying to predict a future state.

It seems that once a system reaches a certain minimum complexity level, its specific behavior becomes completely unpredictable over time without actually observing the system to see what will happen. A New Kind of Science by Steven Wolfram popularizes this idea as the "Principle of Computational Equivalence" –

"Almost all processes that are not obviously simple can be viewed as computations of equivalent sophistication". – (A New Kind of Science, page 717).

Wolfram supports his Principle with analysis of hundreds of systems and processes from a diverse set of domains, and claims important implications for the Principle. The most obvious implication is that, once a system has reached a certain level of complexity, trying to predict its future by using computational shortcuts, formulas, or intution, will very often fail.

I think Wolfram's Principle of Computational Equivalence closely matches our experience with trying to predict the future and extrapolate the past within human society. Prognosticators have long claimed to be able to foresee future events, but they have a poor track record indeed. Ask any economist what the state of the economy will be, any MBA what company's stock will be high, or any professor of world affairs what the major flashpoints for world conflict will be, in only a few short years, and while they may very well give you their opinion, and wax eloquent about technical details in their field and complex models which they may consult, they will also almost certainly be wrong. Just as most economists incorrectly predicted financial stability through the period of 2007/2008 ( http://knowledge.wharton.upenn.edu/article/why-economists-failed-to-predict-the-financial-crisis/), most mutual-fund managers will find that they cannot beat the odds of the market for long, but will instead regress to the mean in the long run (for proof, compare the long-term returns of the largest mutual funds relative to plain Exchange Traded Funds).

The difficulties which arise when attempting to predict the future are very similar to the previously mentioned difficulties with complexity which often arise in software development. Prognosticators attempt to predict the outcome of an immensely complex system (the world) with myriad free variables. Because the world is more complex than any person can make an effective mental model of (besides using various heuristics which may or may not appear correct in hindsight), the track record of people trying to predict what will happen in the future is extremely poor.

Similarly, in software development we work with very complex systems. In some respects, software development could be considered less complex than international politics, but in other respects, it could be considered more complex. Modern software development involves coordinating the execution of billions of networked logic units over time. While you may be able to largely understand the physics for the operation of a single transistor within a computer (complete with various quantum and traditional analog phenomena) you can certainly not completely understand or predict the operation of a machine with billions of interacting transistors (which is what today's computers are). Rather, you take certain assertions about your machine on faith, and assign them a very high degree of confidence. When something goes wrong with your computer, then, your limited knowledge about how your computer works allows you to assign an informative prior over the sample space of possible issues with your computer, and quickly zoom in to the likely cause of the issue. When a person is developing software, if he does not have good enough mental model of the processes he is trying to control, he will almost certainly find that the project does not go as expects.

4 Conclusion

In this paper, we discussed subjectivity and complexity in the context of software development. We discussed how humans' intuitive ability to operate in the presence of subjectivity gives us a key advantage over mechanical automata such as computers. We also discussed how real-world phenomena often display a great deal of apparent complexity as well as subjectivity. Wolfram's Principle of Computational Equivalence argues that there is often no shortcut to predict the future state of a system, as you must run a computation of equivalent complexity to the system itself in order to predict the future state of the system. Just as it proves difficult to predict the future state of the world, because we have no effective means to simulate the operation of the world, it is difficult to to predict the success or failure of a project such as a software project if the project leader does not have an effective grasp on all the important variables, considerations, and plans, so that he can mentally compute all the possible outcomes.

As long as programmers make appropriate simplifying assumptions and form an effective mental model of the interacting pieces of the program, software development can proceed quickly and efficiently. The moment, however, that a programmer loses an effective grasp of how the system he is working on works, the programmer is facing the same scenario as the prognosticator – how can you predict how something will pan out when you do not have an appropriate understanding of the forces at play?


On Abstraction

Posted: 2015-09-15. Modified: 2016-01-06. Tags: programming, philosophy, Opinion.

The difference between the right abstraction and the wrong abstraction is a huge difference in simplicity and clarity.

"I do believe that bulk, in programming or writing, can sometimes be an inverse measure of clarity of thought." – Leland Wilkinson, The Grammar of Graphics

bloatware reflects design-by-committee and sloppy thinking.

propositional logic vs predicate calculus

A programming problem can be described as a set of

preconditions

and requirements.

Every programming problem has an infinite number of solutions

no-free-lunch theorem


A hope for quality software

Posted: 2015-09-15. Modified: 2016-01-06. Tags: Opinion, programming, philosophy.

I believe that if something is ever good, in a complete sense, then it will always be good. Human nature does not change, and our core needs change very little. If a meal was good 2000 years ago in Jesus' time, I think we would still find it good today.

One thing that bother s me about software development is that the field is often incredibly fad-driven. People write code, and two or three years later people think they need to rewrite everything to interface with whatever the new hotness is. Look at the state of javascript libraries/frameworks for a prime example of this code churn.

Is it possible to write good code? I think that if you target the right abstractions, then it most definitely is. And one example of this is the long-term success of the Netlib libraries, developed continuously for over 40 years as high quality linear algebra tools.

"Math has a long shelf life".


Turing Machines are Overrated

Posted: 2015-09-15. Modified: 2016-01-06. Tags: programming, philosophy.

Constraints of runtime environments mean that not all turing-complete languages are equally powerful. Much of computing is pushing electrons over wires, not performing symbolic manipulation in the Turing sense. Therefore Turing equivalence of two languages does not necessarily imply that you can perform the same tasks in both of them – one may have drivers written to communicate directly with your gpu, while the other doesn't, for example.

Besides running "algorithms", computers can also interact with their environment. The Turing machine model models everything that can be done with the former capability, but nothing that can be done with the latter. This is a massive omission, and of course puts a lie to the "idea" that all programming languages / runtime environments / computers are equivalent. If computer A has freely available networkable features, while computer B is a strictly self-contained "algorithm" device, then there is an entire world of things you can activate or interact with with computer A which you can't with computer B.


No One Knows How to Do Anything Anymore

Posted: 2015-09-15. Modified: 2016-01-06. Tags: Opinion, programming, philosophy.

Do you think you know how to use piece of software X? No you don't. You've just learned enough of the facade of X that you can often get by without having to look for directions.

Much of modern software development (and life in general, for that matter), is crawling through the vast trove of information available on the internet to find a pre-made solution to a problem at hand. My observation, at least, is that programmers rarely take (or have) time to develop a thorough understanding of a problem or tool. Rather, we rush through assignments and tickets, pasting together components until it seems like we have what we need.

Forget algorithms and datastructures, the most important skill for a modern programmer to have is – google skills.


Proper Confidence: Faith, Doubt and Certainty in Christian Discipleship

Posted: 2015-09-15. Modified: 2015-12-21. Tags: philosophy, Christianity.

Author: Lesslie Newbign

Interesting Christian theology book which attempts to do an end-run around apologetics, claiming that the entire field is catering to to debate in a specific arbitrary world-view. It claims that the Christian/Jewish history is a basis for an alternate way of thinking about the world distinct from the philosophical ideas proposed by the greeks and Romans which we still rely on today. I also felt like this book was somewhat of a "CliffsNotes" guide to various philosophical positions from a Christian perspective. Highly recommended to Christians or Seekers who want to have their mental horizons broadened a bit.

Atom Feeds:
Tags: