way. This is the first story of a series about this methodology.
Simplicity
The quality or condition of being easy to understand or do.Oxford dictionary (https://www.lexico.com/en/definition/simplicity)
that they should be understandable. Simplicity guarantees that its
understandability isn’t an intellectual pain.
First step: architecture
“Architecture is about the important stuff. Whatever that is.”On first blush, that sounds trite, but I find it carries a lot of richness.
It means that the heart of thinking architecturally about software is to decide what is important, (i.e. what is architectural), and then expend energy on keeping those architectural elements in good condition.
software domain. Here we define domain objects and we express clearly:
- what the domain does as input port or use case (I prefer the latter because expressiveness).
- what the domain need, to fulfill use cases, as output port.
technology. Instead low level concept depends upon high level concept.
In other words our code is technology agnostic.
The real important stuff, the domain, is isolated and expressed clearly.
Code
network speed and so on) of the machine and it exposes them through REST API.
- the main use case, expressed as GetCapabilitiesUseCase
- the object that describe the machine capabilities, expressed as Capabilities
public interface GetCapabilitiesUseCase {
Single<Capabilities> getCapabilities();
}
@RequiredArgsConstructor
@Value
@Builder
public class Capabilities {
private final String javaVersion;
private final Long networkSpeed;
}
- java version, expressed as GetJavaVersionPortOut
- network speed, expressed as GetNetworkSpeedPortOut
public interface GetJavaVersionPortOut {
Single<String> getJavaVersion();
}
public interface GetNetworkSpeedPortOut {
Single<Long> getNetworkSpeed();
}
@RequiredArgsConstructor
class Analyzer implements GetCapabilitiesUseCase {
@Override
public Single<Capabilities> getCapabilities() {
return Single.just(Capabilities.builder())
.flatMap(this::getJavaVersion)
.flatMap(this::getNetworkSpeed)
.map(CapabilitiesBuilder::build);
}
private Single<CapabilitiesBuilder> getJavaVersion(CapabilitiesBuilder builder) {
return getJavaVersionPortOut
.getJavaVersion()
.map(builder::javaVersion);
}
private Single<CapabilitiesBuilder> getNetworkSpeed(CapabilitiesBuilder builder) {
return getNetworkSpeedPortOut
.getNetworkSpeed()
.map(builder::networkSpeed);
}
private final GetJavaVersionPortOut getJavaVersionPortOut;
private final GetNetworkSpeedPortOut getNetworkSpeedPortOut;
}
interfaces. For this reason I made the implementation as package
private. In this way we program an interface and not an implementation.
public class UseCaseFactory {
public static GetCapabilitiesUseCase getCapabilitiesUseCase(
GetJavaVersionPortOut getJavaVersionPortOut,
GetNetworkSpeedPortOut getNetworkSpeedPortOut
) {
return new Analyzer(getJavaVersionPortOut, getNetworkSpeedPortOut);
}
}
Conclusion
describe the important stuff - the domain - without any technological
dependency. Obviously the programming language and the library for the chosen paradigm are excluded.