Refining @Pablo's good answer, with definitions (below) and adding a check-list for each method, constrainting their use.
Block layer is a SQL table with polygons representing the city blocks boundaries, which or without sidewalks, but preserving private (see front-1) or non-adressable alleys (see front-2) into the block.
Lot layer is a SQL table with polygons representing land lots boundaries.
Street layer is a SQL table with lines representing streets... Or, in a "river land" also rivers (and a railway can be a "front"?).
Front-1: the @Pablo's methods are about a general concept of front , where some lots have more than "one front about one street", because are at the corner (have two or more front-segments about all its surrounding streets).
Front-2: "front" is about the street indicated in the oficial address (or correspondence address) of the lot. Them, all lot (even at corner) have only one front-street-segment. PS: if your address system and block layer accept lots of an "horizontal condominuim" and its condo-addresses, the "private streets" must showed as usual streets.
The @ChristianAbreu's question illustraion show Front-2 concept (!), not the general one.
Technical note: you can plug Python with PostGIS or with any other OGC-compliant tool (for spatial SQL) to express formally the checklists.
Check-list for method#1 - side of a polygon that does not touch any other polygon
This method have a topologic approach, is valid only for blocks where all lot's areas form their block's area. So, to use this method, you need block layer.
Expressing formallly: check if
blkarea~=sum_lotarea for each block,
SELECT ST_Area(geom) INTO blkarea FROM block WHERE gid=each1;
SELECT SUM(ST_Area(geom)) INTO sum_lotarea FROM lot WHERE gid_block=each1;
Or, if the goemetries are not exact, or if the blocks are with sidewalks, use the least w for
ST_Buffer(block.geom,-w) that ensures
ST_Within(lot.geom lot,ST_Buffer(block.geom,-w)) for all lots.
NOTE: check also
if all lots are within a block,
ST_Within(lot.geom,block.geom) for all lots and associated blocks.
if, for all non-disjoint lots, there are no overlaped areas.
not(ST_Overlaps(a,b)) or this intersection area have no significance (that is
Check-list for method#2 - the side of the polygon closest to a road
This method have a geometrical approach, based on minimal euclidean distance.
Check if the street layer have only "public streets", because you must to separate "public streets" (that can express the oficial address of a land lot) from "alleys" (can be internal of the lot or a "condo-block").
Then, check visually, if all "visual blocks" are surrounded by streets. If your street layer is incomplete, the method is not valid for that blocks.
Conclusions: rules for choose methods
For Front-1 definition:
A) When you have good street data, use method#2;
B) When you have block layer and consistent lot layer, use method#1
C) When you have no good data, try split your spatial data into portions where you can use one or another method. PS: even without the block layer you can build joining neighboring lots, or by a good answer of this question.
For Front-2 definition: you need good street data, because Front-2 definition need street name (of the lot address). Use method#2 and drop front-segments that not have the same street name than the lot address.