Micro-services in a context of high complexity and low code quality

Arseni Mourzenko
Founder and lead developer
177
articles
June 26, 2015
Tags: short 50 productivity 36 quality 36 refactoring 12

One of the most prob­lem­at­ic things of a soft­ware de­vel­op­er is how to han­dle the in­creas­ing com­plex­i­ty of a giv­en code base and the de­creas­ing qual­i­ty of it. Code which, when orig­i­nal­ly writ­ten, was read­able and un­der­stand­able, looks com­plete­ly scary two years lat­er, af­ter dif­fer­ent de­vel­op­ers had to add fea­tures, while not hav­ing enough time to do as much refac­tor­ing, test­ing and doc­u­men­ta­tion as they would like.

High qual­i­ty code with low tech­ni­cal debt is some­thing we all strive to de­liv­er, but busi­ness con­straints don't usu­al­ly make this nei­ther prac­ti­cal, nor pos­si­ble. Dead­lines and low bud­get make it dif­fi­cult to en­sure ex­cel­lence in our dai­ly work, and this, even when man­age­ment is smart enough to think long and medi­um term, not very short term and to hire smart peo­ple and get out of their way.

I strong­ly be­lieve that we can eas­i­ly come with this in­creas­ing com­plex­i­ty and de­creas­ing qual­i­ty through the use of mi­cro-ser­vices. Let me ex­plain.

In­ter­face-based pro­gram­ming

Ob­ject ori­ent­ed pro­gram­ming, and more specif­i­cal­ly in­ter­face-based pro­gram­ming is al­ready do­ing a great job of iso­lat­ing parts of the code base from each oth­er, thus sim­pli­fy­ing main­te­nance and re­duc­ing com­plex­i­ty. As a re­sult, a de­vel­op­er who needs to work on a spe­cif­ic part of the code base can fo­cus on a spe­cif­ic code block which in­ter­acts with oth­er blocks through one or sev­er­al in­ter­faces. As soon as in­ter­faces:

thinks work pret­ty well. In prac­tice:

De­spite those is­sues, in­ter­face-based pro­gram­ming does more good than harm: it still al­lows to fo­cus more than not on a very spe­cif­ic and small part of the code base, while not hav­ing to think too much about the out­side code.

Pub­lic APIs

Un­like in­ter­faces, pub­lic APIs go much deep­er into the idea of con­strained, iso­lat­ed parts of the code base. The most im­por­tant as­pect is the way they han­dle changes in their pub­lic in­ter­face.

The pub­lic as­pect means that as soon as the API is re­leased, there is ab­solute­ly no way to change the in­ter­face. At least, you can't do any change you want. You can ex­tend the in­ter­face with ad­di­tion­al func­tion­al­i­ty, but you can­not change the func­tion­al­i­ty which al­ready ex­ists.

This for­mal ap­proach is not that bad, since it makes the de­sign­ers of the API think twice about the in­ter­face. In ob­ject ori­ent­ed pro­gram­ming, an in­ter­face with­in a code base doesn't re­ceive that much at­ten­tion, be­cause it is nat­ur­al to think that such in­ter­face is easy to change lat­er.

The sep­a­ra­tion be­tween chang­ing ex­is­tent func­tion­al­i­ty and ex­tend­ing one is im­por­tant as well. Some APIs are clev­er­ly thought so that adding func­tion­al­i­ty can be done with ease.

Iso­lat­ed en­vi­ron­ment

Ser­vices (such as pub­lic APIs) pre­sent an ad­di­tion­al ben­e­fit over the in­ter­faces: they are de­ployed in iso­la­tion from their con­sumers. By this, I mean that if I have a stor­age ser­vice which is used by im­age shar­ing ser­vice, video shar­ing ser­vice and on­line doc­u­ment col­lab­o­ra­tion tool, I can host stor­age ser­vice on a lo­cal Win­dows Serv­er for a while, then com­plete­ly rewrite it and mi­grate it to a Lin­ux-based cloud provider: both shar­ing ser­vices and the col­lab­o­ra­tion tool would be com­plete­ly un­af­fect­ed; their re­spec­tive de­vel­op­ers wouldn't even know that the stor­age ser­vice was com­plete­ly rewrit­ten and moved else­where.

And this is a huge, huge ben­e­fit. With in­ter­faces, you see, you al­ways have to keep in mind the en­vi­ron­ment. You can't rad­i­cal­ly shift to a dif­fer­ent pro­gram­ming lan­guage or ecosys­tem, with­out af­fect­ing se­vere­ly the com­po­nents which in­ter­act with you through in­ter­faces. With ser­vices, you can do this with ease.

Con­clu­sion

Mi­cro-ser­vices look promis­ing when it comes to cre­at­ing loose­ly cou­pled com­po­nents form­ing a larg­er sys­tem. The care one should take in de­sign­ing the pub­lic API and the iso­la­tion of every com­po­nent which ab­stracts not only the ac­tu­al im­ple­men­ta­tion of the in­ter­face, but also its en­vi­ron­ment, makes mi­cro-ser­vices a great tool for cre­at­ing main­tain­able sys­tems where dif­fer­ent parts can be rewrit­ten on de­mand with ab­solute­ly no ef­fect on oth­er parts of the sys­tem.

In a world where busi­ness con­straints make it im­pos­si­ble to pro­duce ex­cel­lent code with prac­ti­cal­ly no tech­ni­cal debt, mi­cro-ser­vices might be the tool we need to pre­vent com­plex­i­ty and low qual­i­ty from hunt­ing our pro­jects for­ev­er.