Useful Programming Language
A UsefulProgrammingLanguage is one that (simultaneously):
-
to meet useful functional requirements (as demanded by a domain)
-
while also meeting a variety of pervasive concerns, including:
-
performance
-
efficiency: ability to achieve high performance with very few resources
-
utilization: ability to use full power of machine to achieve high performance
-
latency: time between a cause and a given effect. There is hardware latency and software latency; a good programming language should allow minimizing total latency, which requires taking full advantage of hardware capabilities.
-
multi-dimensional: space, cpu, power-consumption, bandwidth, latency
-
reliability
-
robust: a system is robust if it keeps working even in adverse conditions. This includes working under contract violations (where programmers mess up). In an open system, robustness is necessary for security - and vice versa - due to malicious coders (denial-of-service attacks, etc.) Robustness for dataflows and event-flows is aided by supporting such techniques as failover, redundancy, caching, and GracefulDegradation - automatically switching to another service, possibly in stages, and even falling back on cached values when the primary services are disabled.
-
resilient: a system is resilient to the degree that it quickly and completely recovers from adverse conditions. Poor resilience requires manual intervention restarting whole applications, maybe the whole computer, or possibly even a whole network of computers (and starting them up in a particular order), to recover from error. It might require reformatting a drive. More resilient systems are self-healing (i.e. quickly recovering from fallbacks or failure), involve resetting the minimum possible.
-
disruption tolerant
-
graceful degradation:
-
resilient: recovers quickly, correctly, and automatically once source of problem eliminated
-
available: uptime ratings (how many "nines"?)
-
predictability
-
temporal: ability to predict temporal properties of a process
-
realtime: ability to bind latencies (both upper and lower bounds) for a given process
-
terminating: weaker than realtime; ability to say that a given process will terminate in certain ways.
-
synchronization: ability to ensure two otherwise-independent processes have the same latencies
-
embedded: ability to bind space costs (upper bounds) for a continuous process
-
clueless programming: ability to know the characteristics of a composed system without knowing implementations of the components. (i.e. cannot use locks for concurrency since two components using locks might be independently correct but then deadlock when composed)
-
reliability: ability to prove certain forms of resilience or robustness
-
partial-failure handling: ability to predict how system behaves under partial failures from end-to-end.
-
consistency: ability for different observers to agree on a property. (Implies consensus, not determinism.)
-
bounded inconsistency: bounded inconsistency in a distributed observer system.
-
eventual consistency: unbounded inconsistency, with the provision that if updates stop then everyone will eventually reach a consensus on what they should be seeing.
-
determinism: lack of observable randomness; given inputs and initial state, output and final state are fully specified. Does not preclude non-observable non-determinism.
-
modularity
-
delay of choice: code defined outside module can affect module
-
component packaging: provision of software units
-
matchmaking and linking: ability to meet logical demands from one software unit to another (i.e. "I need HTTP access" is met by "I provide HTTP access" by examining a repository of software components).
-
live services: ability to hook into 'real' systems
-
confinement: ability to logically replace or intercept access to 'real' systems without modifying the accessing code.
-
maintenance
-
changing requirements
-
changing environment: new hardware, new OS
-
backwards compatibility
-
system administration
-
distributed components
-
install: distribution of components
-
uninstall: ability to cleanly remove or eliminate unnecessary components after installing them
-
dependency management (avoiding DllHell)
-
ConfigurationManagement
-
PolicyInjection
-
security - a variety of environmental concerns
-
confinement: limiting the damage from running someone else's code on your machine
-
authority: end-to-end ensuring that operators do no more than they are allowed
-
privacy: protecting secrets of both users and businesses that need to distribute things. two-sided DigitalRightsManagement.
-
robust privacy: protects against accidental leaks by programmers and users, i.e. by having well-defined secrecy-violation exceptions, by censuring, by constraining automatic distribution based on secrecy.
-
resilient privacy: helps patch up after a programmer or user leaks data; doable via auditing, WebOfTrust, cutting off unauthorized systems quickly.
-
access: ensuring availability of service to authorized users in presence of external attempts at attack or sabotage
-
stealth: limiting noisy communications in case of eavesdropping or military purpose
-
anonymity: resistance to tracking communications between a data-source and a subscription
-
composition and reuse of code written originally for some other purpose
-
scales to large numbers of programmers
-
premature abstraction shouldn't hurt performance (i.e. ability to 'flatten' abstractions in a staged compilation)
-
premature optimization shouldn't hurt abstraction (i.e. with compositional gotchas, like deadlocks)
-
'clueless' programming: programmers should be able to remain ignorant of implementation details
-
'iterative' or 'exploratory' programming: programmers must be able to learn and achieve progress with the 'write sloppy then fix' approach
-
stigmergy: programmers make mistakes, so the language (and IDE) would do well to automatically guide a collection of programmers to fixing the mistakes rather than burying them. (May benefit from FirstClass support for UnitTests to allow ZeroButtonTesting and other features)
-
implementable: no language primitive shall involve any 'magic'; ideally, the implementation of each primitive is simple and straightforward.
-
analyzable: designed for certain analyses to improve reliability, security, performance, etc. RicesTheorem suggests delaying TuringEquivalency as far to the edges of the language as possible