10

I do line of business apps where the all the other developers are used to doing basic CRUD apps or are focused solely on making pretty/functional interfaces and I am getting the following a lot.

"With the way we use to do it Employee would have all the things you could possibly do with an employee." And it was true. That one "Class" had thousands of lines of code and anything you could do with an employee was there. Or, even worse, there was a table of employee data and each developer figured out how to do what they wanted to do in the event handler.

All the bad things about that approach was true but at least the developer using employee could, without going to other documents, figure out how to enroll the employee in a health plan, give a pay raise, fire, hire, transfer etc. Same goes for Manager and all the other major ideas. Or, if they used the employee other needed data tables, could just do what they wanted.

Yes, there was much duplicated code. Yes it was very brittle code. Yes testing it was way more difficult than necessary. Yes changing functionality was fear inducing and Copy Paste was a natural due to the approach.

But they could at least discover what was available by creating one class or they could do what they need to get done without having to understand the difference between interfaces, abstract classes, concrete classes etc. And they didn't have to search anything other than the methods returned by intellisense or know the tables where the data resided.

I have googled/binged and even yahoo!d but I haven't found any acknowledgement of this problem.

So maybe there isn't a problem and I am just missing something. I have racked my brain trying to figure out a solution where the developer(s) that do not work the actual behavior/design can easily discover how to do something without having to reference any external documents or scan the class names in the various components/projects to find the one that sounds like it will work.

The only thing I have been able to come up with is have these, for lack of a better name, "Table of Content Class" that does nothing more that return the actual classes (and really most of them are interfaces but they don't know the difference or even care) that other developers can use to perform the actual tasks desired. Still end up with really big classes but there is almost no behavior in them.

Is there a better way that doesn't require intimate knowledge of the middle tier where the actual implementation of SOLID takes place?

Basically what I am asking is there a way to allow CRUD type developers continue to be CRUD developers in a very complex system

ElGringoGrande
  • 2,913
  • 22
  • 20
  • 8
    Maybe have your developers not depend entirely on IntelliSense (or equivalent) for discoverability. Name things well. Document things well. This is a communication problem, not a technical problem. – Rein Henrichs Oct 09 '11 at 20:02
  • Hmmm. Kinda. The more I think about it the more I believe there is a business opportunity lurking about. – ElGringoGrande Oct 10 '11 at 01:45
  • 2
    @ReinHenrichs: If the developer needs to read documentation, it will take them time and the productivity will suffer. So it is important they find out what they need for given task quickly. It does not have to rely on intellisense, but it better be easy. Making it easy is certainly a technical problem. – Jan Hudec Oct 10 '11 at 06:21
  • @JanHudec: No, it is not a technical but an organisational problem of using proper conventions for naming, layout and whitespace. Without naming conventions, you wouldn't know what to search for. Without consistent naming, you wouldn't find everything and/or have a much harder time tracing everything back. Without consistent layout and use of whitespace (especially in type declarations) you wouldn't find half the instances you need. Yes a better regex could help, but I don't want to learn regex just to find where a class is used. – Marjan Venema Oct 10 '11 at 07:24
  • @JanHudec It's not an "if" but a "when". Developers will need to read documentation. If you want them to "find out what they need for given task quickly", your best bet is to focus on making the documentation effective. Don't try to solve a people problem (like communication) with a technical solution. It. Does. Not. Work. – Rein Henrichs Oct 10 '11 at 21:22
  • as long as your dependencies are named reasonably correct, i'd say that developers should be able to figure out what each dependency does or where a given functionality is present. – silverCORE Oct 11 '11 at 18:52

3 Answers3

4

It seems that what you've described (i.e. Employee class having ALL possible code that you could do with an employee) is an extremely common pattern that I've personally seen quite a lot. Some of that code I've written myself before I knew any better.

What starts off as a class that is supposed to represent a single entity with manageable set of methods, morphs into something that is a nightmare to maintain because each feature and each release keep adding more and more to the same class. This does go against SOLID principles that say you should write a class once and resist the urge to modify it over and over again.

A while ago (before I discovered design patterns or SOLID as promoted by others), I decided for my next project to flip things around a bit. I was working on a server that served as an interface between two very large platforms. At first, only synchronization of configuration was required, but I could see that this would be a logical place for many other features.

So instead of writing a class that exposed methods, I wrote classes that represented methods (turned out to be "Command" pattern from GoF). Instead of doing the work for the client, all my main application classes became persistent state holders and they became much shorter in length. Every time I had to add a new interface method to the service itself, I would simply create a new class that had Execute() method that started everything. If multiple commands had something in common, they derived from the common base class. Eventually the thing had 70+ different command classes and the entire project was still very manageable and was actually a pleasure to work on.

Your "TOC class" is not too far off from what I did. I had an abstract factory (GoF) that was responsible for instantiating commands. Inside the factory class, I hid most of the details behind the base class and ATL-style macros, so when a programmer had to add or look up a request, they went in there and all they saw was:

BEGIN_COMMAND_MAP()
    COMMAND_ENTRY( CChangeDeviceState )
    COMMAND_ENTRY( CSetConfiguration )
    ....
END_COMMAND_MAP()

Alternatively (or in addition to), you could put all your actual command classes into a separate namespace so when people are coding and need to run something, they just type namespace name and Intellisense lists all the commands that you've defined. Then each command includes all get get/set methods that determine exactly what input and output parameters.

You can also explore the use of Facade (GoF) pattern. Instead of exposing 1000+ classes to your CRUD engineers. Hide all of them behind a single class that exposes only what is needed. I would still stick to having each "action" be its own class, but your Facade class can have methods that would instantiate each of your actions and again, with Intellisense they'd see immediately what is available. Or have Facade have actual methods, but internally make them instantiate commands, queue them up and wait for responses. Then return as if a regular method call was made.

(*) I didn't want to get into too many details, but I actually had "Command" and "CommandHandler" set of classes. This separated responsibility of managing/queuing/serializing in/out parameters from classes that actually "handled" those commands.

DXM
  • 19,932
  • 4
  • 55
  • 85
  • Yes. I realized today that what we have ended up with is a badly implemented Facade pattern. I do not think there is anything more to do other than breaking the big facade into smaller ones. I do like your idea of incorporating some command classes behind the scenes. – ElGringoGrande Oct 19 '11 at 01:26
0

It can be a problem. Particularly if you name things badly. But there are a number of solutions to it without resorting to complex classes. Heck, a class with too many methods can be equally difficult to navigate with Intellisense.

Try using namespaces (C#) or packages (Java), or whatever similar concept your language has (I'll refer to them all as namespaces), to simplify the problem.

Start with your company name. That limits Intellisense to only namespaces written by yourselves. Then, if you have multiple applications, use the second part of the namespace to split those up. Include a Core namespace, for stuff that exists across applications. Next break things down into types of functionality. And so on.

If you do this right, you'll end up with very discoverable items.

To take your example, if I want the User validation, I type "MyCo." and it gives me a list of application namespaces. I know the User database is used in all our apps, so I type "Core." then I get a list of types of functionality. One of those is "Validation" so that seems like an obvious choice. And there, within Validation, is "UserValidator" with all its functionality.

As it happens, for things I use a lot, I'll quickly remember the names, or at least the conventions. Because I make a lot of changes to validation rules, I will know that all my validation classes are called FooValidator, where Foo is the name of the table. So I actually won't need to traverse the namespaces. I'll just type UserValidator and let the IDE do the rest of the work.

But for things I can't remember, it's still pretty easy to find them. And when I do, I can remove the namespace prefix.

pdr
  • 53,387
  • 14
  • 137
  • 224
  • It is, in part, bad naming by me. The names are not horrible but I often think of a better one months after the fact. But even with good names if you have thousands of classes names are not always easily discoverable. I am trying to overcome this. I just thought there might be a known way. – ElGringoGrande Oct 10 '11 at 01:41
0

Since you refer them as basically "CRUD" developers, we'll assume you don't think they are very good. We don't know if this means they also don't understand your business domain. If they understand the domain, the classes should make sense to them. Knowing several classes have been built, they should take a look first, ask second, consider building from scratch as a third option.

As far as knowing how to automatically know how to use/reuse a class just by looking at it shouldn't be expected the first time. You're going to need to document and possibly provide additional explanation either through training or possibly during code review.

Many API's and open source projects provide documentation, code examples and other explanations. Yours may not need to be as user friendly, but there's no getting around it. Teach them well.

JeffO
  • 36,816
  • 2
  • 57
  • 124
  • No. CRUD doesn't mean they are not any good. They are developers that have always dealt with basic data applications. CRUD = create, read, update and delete. I fail to see how that makes them bad programmers. – ElGringoGrande Oct 10 '11 at 01:34
  • In british english slang, "crud" == "shit". – Michael Shaw Oct 18 '11 at 00:27