an interface is a shared boundary across which two or more separate components of a computer system (Wikipedia contributors, 2024a)
Ethernet 1000BASE-T | DisplayPort 1.2 | USB 2.0
interface is an agreement
- how a module / component will work
- so as long as the agreement is complied the components do not need to
know about the internal structure/work of the other components
- separation of concerns
- single responsibility principle
a 327 Million Dollar interface miscommunication
NASA and Lockheed Martin mixed up units for the Mars Climate Orbiter (1999)
- spacecraft sent values back to Earth in Newton seconds (kg⋅m/s)
- the software in the ground station read those results as pound
seconds
- the guidance and navigation teams was off by a factor of 4.45 times
- this led to a miscalculated trajectory, which doomed the probe and the mission
based on (Dodd, 2020), read the full story written by Tim Dodd
the most important elements of the design are the interfaces, hexagonal arcitecture focuses on them
user statistics example - interfaces
data sent to the UI
specify
- the JSON schema
- endpoint
- etc.
user statistics - C4 component
interface mocking
- an interface is a boundary where a module can be separated
- in the user statistics example there are two parts: a backend and a frontend
- with a well defined interface, the frontend can work regardless of the
backends’s state
- e.g., using a mock backend
A mock, in software engineering, is a simulated object or module that acts as a stand-in for a real object or module (GeeksforGeeks, 2019).
user statistics - mock backend
require 'sinatra'
def generate_progress
rand.round(2)
end
def generate_activity_matrix
result = []
(1..4).each do |_w|
daily = []
(1..7).each do |_d|
daily.push rand(10)
end
result.push daily
end
result
end
get '/user/:id/statistics' do
data = {}
data['name'] = 'Marvin'
data['id'] = params['id']
data['registration'] = '2019-10-02'
data['progress'] = generate_progress
data['activity'] = generate_activity_matrix
return data.to_json
end
http://localhost:4567/user/42/statistics
{
"name": "Marvin",
"id": 42,
"registration": "2019-10-02",
"progress": 0.92,
"activity": [
[4,9,7,4,7,1,8],
[9,8,1,8,4,1,7],
[3,6,8,4,2,4,5],
[3,5,5,3,2,9,7]
]
}
frontend development
a mock backend should be enough for a frontend developer to create and test the user statistics view of the user interface
{
"name": "Marvin",
"id": 42,
"registration": "2019-10-02",
"progress": 0.92,
"activity": [
[4,9,7,4,7,1,8],
[9,8,1,8,4,1,7],
[3,6,8,4,2,4,5],
[3,5,5,3,2,9,7]
]
}
it may be presented to the customer
fast feedback, agile, and so on…
do not change the interface (without notice)
this will break the frontend
it is not just rude, but will waste the time of the other team (with pointless debugging)
do no break the userland
the number one rule of kernel development is that “we don’t break users”
API changes should be communicated
- during design / development
- change can be necessary / allowed, but communicate towards the impacted teams
- diagrams show inner dependencies
- services announce API deprecations
- so as library / framework developers
- can be a source of new issues even if downstream code is not changed
API versions
- 2021-06-30: API v1’s end of live
- service does not accept connections via APIv1
- code can be removed (no need to maintain it anymore)
https://developers.facebook.com/v21.0/me?fields=id,name
language level
GeoPandas 1.0 / new deprecations: unary_union attribute is now deprecated and replaced by the union_all() method (#3007) allowing opting for a faster union algorithm for coverages (#3151)
from shapely import Polygon
import geopandas as gpd
p1 = Polygon([[1, 2], [3, 2], [3, 4], [1, 4]])
p2 = Polygon([[2, 3], [4, 3], [4, 5], [2, 5]])
gpd.GeoDataFrame(geometry=[p1, p2]).unary_union
DeprecationWarning: The ‘unary_union’ attribute is deprecated, use the ‘union_all()’ method instead.
def unary_union(self):
warnings.warn(
"The 'unary_union' attribute is deprecated, "
"use the 'union_all' method instead.",
DeprecationWarning,
stacklevel=2,
)
return self.union_all()
source: github.com/geopandas/geopandas
java
public class Worker {
/**
* Calculate period between versions
* @deprecated
* This method is no longer acceptable to compute time between versions.
* <p> Use {@link Utils#calculatePeriod(Machine)} instead.
*
* @param machine instance
* @return computed time
*/
@Deprecated(since = "4.5", forRemoval = true)
public int calculate(Machine machine) {
return machine.exportVersions().size() * 10;
}
}
source: (Ozler, 2019)
IDEs can parse the deprecation decorators and show to the developer during work
discussion: Hyrum’s Law
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.– Hyrum Wright, 2012
example to Hyrum’s Law
/user/<id>/statistics
{
"name": "Marvin",
"id": 42,
"registration": "2019-10-02",
"progress": 0.92,
"activity": [
[4,9,7,4,7,1,8],
[9,8,1,8,4,1,7],
[3,6,8,4,2,4,5],
[3,5,5,3,2,9,7]
]
}
no documented /users endpoint, but existing implementation
get '/users' do
data = {"ids" => [42]}
return data.to_json
end
sooner or later someone will discover the undocumented behavior and depend on it
think like a villian, someone who’s going to abuse the system that you’re designing and building
discussion: Postel’s law
Be conservative in what you do, be liberal in what you accept from others.
– Jon Postel, in the specification of TCP in 1980 (RFC 761) source: Postel’s Law
Postel’s law / robustness principle
When receiving data, handle variations, minor errors, or deviations where possible. Don’t crash or reject communication over minor issues.
When your system emits data or interacts with the outside world, adhere closely to protocols and standards.
In modern times, overly liberal acceptance can sometimes mask errors, so this law is occasionally tempered with security considerations.
references
Dodd, T. (2020). Metric vs imperial units: How NASA lost a 327 million dollar mission to mars. https://everydayastronaut.com/mars-climate-orbiter/ .
GeeksforGeeks. (2019). MOCK (introduction) – software engineering. https://www.geeksforgeeks.org/software-engineering-mock-introduction/ .
Ozler, H. (2019). Java @deprecated annotation. https://www.baeldung.com/java-deprecated .
Wikipedia contributors. (2024a). Interface (computing) — Wikipedia, the free encyclopedia. https://en.wikipedia.org/w/index.php?title=Interface_(computing)&oldid=1244878409.
Wikipedia contributors. (2024b). Mars climate orbiter — Wikipedia, the free encyclopedia. https://en.wikipedia.org/w/index.php?title=Mars_Climate_Orbiter&oldid=1248652445.