Over Generalization Of Business Logic

I'm suggesting this is added to the ListOfDesignSmells

You want to generalize to eliminate redundancy. But while this is fine at the syntactic level you want to be suspicious at the semantic level.

It's fine to generalize processing of lists with abstractions like Iterators and Comprehensions. But you don't want to see someone make a generalization of entities which are defined at your business logic or application layer. Eg. that Customers are a kind of Contact or Internal'TransferOrders are the same as PurchaseOrders. You may reduce code by assuming that they are, but you're likely to find out in future, that these kinds of RealWorld entities turn out to be different. Then you're into ControlCoupling? (adding extra arguments to a function to allow type-specific behaviour) or adding extra "type" fields etc.

Is this a known AntiPattern?

I don't know. I do know that I've seen it happen and had to clean up the mess afterwords.

Sounds like a case of LimitsOfHierarchies.

: I don't think so. The times I've seen it happen certainly had nothing to do with hierarchies. It's more a matter of conflating two concepts when their implementation just happens to match.

: Could be that BrittleBaseClass? is one symptom or subkind of this AntiPattern.

CouplingAndCohesion sometimes faces off against OnceAndOnlyOnce, especially when some elements of code look a lot like SystemsSoftware. I've seen it happen again and again. I've been the perpetrator more than once. There is a tendency, in these cases, for programmers to attempt to generalize some portion of code into a common framework or API, but doing so often requires extricating the business logic portion, and sometimes there was a good reason for the two to be combined... and so one ends up adding mechanisms (flags, etc.) to violate the new abstractions.

The lessons I've learned are that:

RE: It's fine to generalize processing of lists with abstractions like Iterators and Comprehensions. But you don't want to see someone make a generalization of entities which are defined at your business logic or application layer. Eg. that Customers are a kind of Contact or Internal'TransferOrders are the same as PurchaseOrders.

This is terrifying, or maybe I just lack a sense of humour. The textbooks don't just say that a Customer is a kind of Contact because textbooks are always dumb. You know at the start they are different, and if you use some kind of indirection, you can combine the tasks that users want to do with Contact, such as log calls, generate mail merges, plan visits, with the tasks for a Customer, such as taking orders and dispatching goods. As the textbooks say, the Customer could be an Employee, a Customer, and a Supplier, for all you know, and they are not afraid. Please don't add this to the AntiPatternsCatalog, at least not without allowing me to post my dissenting opinion. Maybe there is such a thing as over-generalization, and I am too much a victim of the consultants that say you must change your business processes to use our software, but Customer is a kind of Contact is not a good example.

{How is that a dissenting opinion? It sounds an awfully lot like a ViolentAgreement.}

ContactAndAddressModels may offer some related suggestions.

I dissent, because my conclusion from this debate is that OnceAndOnlyOnce should always trump this. Generalize as much as you can now, you can specialize later if you find you need it.

{Any argument that OnceAndOnlyOnce should 'always' trump CouplingAndCohesion must ignore technical and political realities. For example, if you write a function for library A and I write a function for library B, and both have some similar structure which could be abstracted OnceAndOnlyOnce into a third framework F, that is technically a violation of OnceAndOnlyOnce. Of course, creating and sharing framework F requires increased coupling between what would otherwise be two independently developed projects.}

{There are times for BigDesignUpFront and generalization. That's when writing interfaces to SystemsSoftware for use by other people, such as programming languages and framework APIs. When writing 'application' software, KeepItSimpleStupid and DoTheSimplestThingThatCouldPossiblyWork can very productively trump generalization and OnceAndOnlyOnce. Generalize only as suggested by local structure of the program - i.e. if you find yourself maintaining behaviors or data described in multiple places to keep them identical.}

OverGeneralizationOfBusinessLogic makes you create GodTables, for example: If you store cities, countries, and flavors of ice cream in a single table (your overgeneralized "GeneralCatalogs?" table), and then add a foreign key relationship to it form another table, that only needs ice cream flavors, the database will not be able to help you to avoid putting a city on the place of an ice cream flavor. Of course, since a lot of developers have FearOfAddingTables, they actually think that creating tables that are more "generic" (and therefore reducing the number of tables in their database) they are actually reducing complexity, when in reality they are increasing it (because now the model does not accurately reflect that countries, cities and ice creams flavors are 3 totally unrelated entity concepts, even if they can both be stored inside a table that has the same field (typically "ID/TYPE/NAME" or "ID/TYPE/NAME/DESCRIPTION")) -LuxSpes

I disagree with excess "thin tables". My personal observation is that they complicate maintenance, but nobody has been able to offer definitive objective evidence either way. No need to rekindle that angry debate here. The "right" amount of generalization of the table depends on the domain situation and ChangePatterns. -t

{I'd say that "generalization" when it comes to naming "tables" is more an issue of sharing tables than of normalizing them. For example: deciding to reuse customer contact-information table for employee contact-information table, or attempting to fit both US and international addressing modes into one table. Over-generalization in these cases tends towards creating GodTables, but from a cause unrelated to maintenance advantages of higher normal forms.}

Why the hell are we arguing about it here? There's already umpteen topics on it. -t

{That's a silly question. You made a choice to argue about it here when you said 'I disagree' then offered what you considered to be a valid reason. If you think it'd be better to argue it elsewhere, then say so, but if you're going to ask rhetorical questions then you really should provide the answers yourself.}

It's only marginally related to "business logic" also. -t

They are more than marginally related, in a system that uses a database to store its data, business logic is all about modifying the data in the database -LuxSpes

Yes, but the wide/thin design decision is not going to change the biz logic itself that much (unless all those joins slow it down so much that a different route needs to be taken.) -t

You think? if you mix entity concepts in the same table you are going to need extra code to split them apart, for example if you have ice cream flavors, and cities in the same table, and you only want the list of cities, you will need to write select * from general_catalog where type=CITY, if you had separated tables you would only have to write select * from CITIES. Or if want to set the city where a person lives, you need extra validation code to prevent your system from accidentally saying that "Mr. Smith" lives at "Dark Chocolate" city. In other words if the database model changes, the code (business logic) that deals with it changes too -LuxSpes

I meant "wide" tables that don't repeat actual data unnecessarily. Mixing ice-cream and cities is pretty obviously bad under normal circumstances. Most of the wide/thin debate does not orbit around such extreme cases. -t

{EntityAttributeValue is a typical pattern that comes of generalizing tables, but may involve as few as three columns. The opening made an explicit example of this (see mention of ID/TYPE/NAME). It is unclear how the 'wide/thin debate' is relevant to over-generalization of tables. Perhaps TopMind should clarify his assumptions.}

Whether it's "over-generalization" depends on the requirements. If the requirements are that the user can add new domain item kinds without calling for a DBA or programmer, then an AttributeTable offers such flexibility. In short, ItDepends. Software engineering is largely about weighing design trade-offs. Almost nothing is always good or always bad.

{I have some issues with what you say. (A) Why would an AttributeTable fundamentally offer this 'flexibility' to a greater degree than other designs? Is there some reason that new tables should be difficult to add? I suspect you're making an assumption on security and code-ownership issues. (B) That flexibility/security/etc. sometimes overrides other concerns seems to be a RedHerring: it does not address concerns or flaws of over-generalization of business-logic in particular. Your basic argument seems roughly equivalent to giving you a GeneralPurposeProgrammingLanguage and saying "that ain't over-generalization of business logic when you need the flexibility" despite the utter lack of any encoded business-logic. It's equally easy to argue that it isn't business-logic at all. (C) You still haven't clarified how any of this is related to the 'wide/thin debate'.}

If you are saying that AttributeTables are a technique, which if mis-used, can lead to over-generalization, then I agree. -t

{What I said is the other way around: over-generalization leads to AttributeTable.}

Exactly, after all AttributeTable is generally implemented only because of the poor design, implementation and support of an unified InformationSchema for all the Sql databases. -LuxSpes

Do you mean implementations of RDBMS (engines) themselves? -t

Precisely what I do not like about the AttributeTable is that it basically is a ad-hoc, informally-specified reimplementation of part of what the InformationSchema should provide. RDBMS should include a read/write InformationSchema that made it easy to interactively modify the structure of any table(s) using DML statements. If the InformationSchema did its job property, we would not have any need to create our own customs instance of the AttributeTable pattern. -LuxSpes

When we use AttributeTable, we only do so because we want to save ourselves the work of creating a new table, or adding a new field in an old table, but what we do not realize is that all the tables in the database can be seen as the result of seeing a an instance of an AttributeTable (the InformationSchema) from another perspective, we only think is more convenient to add row to an AttributeTable than to create a new table because current pseudo RDBMS implementations make it so, if I could create a new table/field by adding rows a "TABLES" or "FIELDS" table, there would be no difference. -LuxSpes

But that is the implementation, isn't it? An app developer cannot change the DML features (or lack of). -t

Yes, but I feel that a lot of times developers are too hasty to implement an AttributeTable when a couple of DDL statements could do the work and offer some advantage (like the prevention of confusion between ice cream flavors and cities). We only see the short term advantages of not having to create a new table of field, and not the advantage of having the entity concept or entity concept attribute clearly visible in the database schema. [-LuxSpes?]

DDL is often awkward, requires heavier access rights, and is inconsistent from vendor-to-vendor, increasing effort to swap DB engines. -t

[Yes, but AttributeTable often has performance implications, significantly complicates queries, and obfuscates human-readability of the data. Welcome to some trade-offs; pick the approach that best meets the requirements.]
The bottom line is that one can over-generalize and under-generalize and they each have their consequences. There are no "hard" rules to know where to set the dial. Experience with both software development and experience with the domain are both recommended prerequisites to making wise decisions. Also, sometimes we will get it wrong because we cannot forecast all possible future needs. No use on beating yourself up for not predicting the future 100%. We'd all be on a golf course with WarrenBuffett if we were such great forecasters. Related: SoftwareDevelopmentIsInvesting. -t
Compare with ExpandToContract where abstraction helps.
See Also: EightyTwentyRule

View edit of August 16, 2010 or FindPage with title or text search