One complaint I hear about models is that they're abstract and therefore not useful. My initial response is "Duh!" to the first but "Huh?" to the second.
Humans cogitate almost exclusively using abstractions, hence the initial response. An abstraction focuses on some properties of an object (not using the term in the OO sense) at the exclusion of others. When we want to reason about some characteristic of a thing - such as its behavior under certain circumstances - we can ignore other aspects as irrelevant to that question, even though those omitted properties may be very relevant to reasoning about other qualities of the object.
Take a chair. If I'm designing the chair, I really need to focus on the parts, how they connect, their structural strength, the stabilty of the base, and so on. If I'm trying to put the chair together, I need the parts list and the order in which those pieces must be assembled. If I'm an interior designer, I care about the chair's style and color. If I'm trying to arrange seating at an event, I care about the physical space it takes up and its capacity. Which model represents the chair?
The answer, of course, is that they all do. Each focuses on some aspects of the chair and elides detail not relevant to the reasoning required of the model.
This does not mean that models, and the abstractions underlying them, are either imprecise or useless. We can, and should, build models for systems and software that are both precise enough and broad enough to support the necessary reasoning. Sometimes, this entails detailed state behavioral modeling; other cases might result in mathematically precise models using languages/tools such as Simulink. In other cases, we'll build detailed architectural structure models to understand what the large scale pieces of the system are and how they connect.
To be generally helpful in systems and software modeling, the models rmust represent precise details about the system but not necessarily all the available detail. For example, I might model a device driver with UML. I precisely specify the structure in a UML class diagram, identifying the set of relevant attributes, their types and subranges, as well as the services that manipulate those attributes. I might also specify the order of the execution of the services within a state machine as the driver responds to various environmental events. I can then generate code using tools such as Rational Rhapsody(tm) and download it to the target, execute it, and visualize that execution using Rhapsody's execution and animation environment. I might very well have elided details about unrelated structural aspects such as links to an event logger implemented as an observer or attributes not related to the device driver manipulation of the hardware. I certainly have omitted specifying the source level language constructs managing the state machine execution. I have certainly not specified which CPU registers should be used. Those details aren't part of the model, but that doesn't mean that the model was imprecise with respect to the behavior and structure relevant to my viewpoint.
There are people who think that source code is the ultimate answer and modeling should - at most - be a very high level vague notional view, scribbled on a napkin and then discarded. I am not among them. I have seen tremendous benefits in the application of models precise enough to support execution/simulation and code generation.
Over the course of an entire project, 10-20 source lines of code (SLOCs) is the norm for software productivity. I understand that when you're actually sitting in front of your computer wielding vi (or Emacs - my wife and I argue about which is best!) to write code, your productivity is higher. Nevertheless, over the lifespan of an entire project, 10-20 SLOCs/day per programmer is typical. Interestingly, this seems to be independent of the abstraction level of the language. This is why source level languages smacked assembly language over the head. You can do a lot more with a line of high level source language than with a single assembly language statement. 10-20 lines of a high level source language might result in between 100 to 300 lines of assembly language. Similarly - properly applied - UML modeling can have a similar magnification of productivity when applied to source level languages. I've seen 200-300 SLOCS/day per programmer for effective modeling teams. It's all about the maturity of the organization with respect to its use of modeling.
I've created a model of modeling maturity for software development teams called the UML Modeling Maturity Index (UMMI), shown below:
The percent benefit is (informally) derived from the observation about the productivity of hundreds of teams using UML and/or SysML with varying degrees of success. As expected, the more mature the modeling an organization applies, the more they benefit from modeling.
To do precise modeling, be sure to specify that is the purpose of the model, and of each diagram. This is the "mission statement" for the diagrams that I talked about in my last blog "Forget 7 +/- 2". Provide all the detail relevant to the purpose of the model and the diagrams. If that purpose is to develop running software, then you'll need to specify the structural elements (classes with attributes and services for OO designs, functions, variables, and data types for structured designs, along with structural relations), state based behavior (with state diagrams) and algorithmic behavior (with activity diagrams or flow charts). This precise modeling of the software structure and behavior takes less effort that writing the equivalent source code and the source code can be generated from it. Further, you get the benefit of automatic design documentation because you know the design represents the actual shipping code.
It's a win-win scenario.