Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-settings.php on line 512

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-settings.php on line 527

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-settings.php on line 534

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-settings.php on line 570

Strict Standards: Declaration of Walker_Page::start_lvl() should be compatible with Walker::start_lvl(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_lvl() should be compatible with Walker::end_lvl(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::start_el() should be compatible with Walker::start_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_el() should be compatible with Walker::end_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_PageDropdown::start_el() should be compatible with Walker::start_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1244

Strict Standards: Declaration of Walker_Category::start_lvl() should be compatible with Walker::start_lvl(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_lvl() should be compatible with Walker::end_lvl(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::start_el() should be compatible with Walker::start_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_el() should be compatible with Walker::end_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_CategoryDropdown::start_el() should be compatible with Walker::start_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/classes.php on line 1442

Strict Standards: Redefining already defined constructor for class wpdb in /var/www/serverdude.dk/public_html/wp-includes/wp-db.php on line 306

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-includes/cache.php on line 103

Strict Standards: Redefining already defined constructor for class WP_Object_Cache in /var/www/serverdude.dk/public_html/wp-includes/cache.php on line 431

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-includes/query.php on line 61

Deprecated: Assigning the return value of new by reference is deprecated in /var/www/serverdude.dk/public_html/wp-includes/theme.php on line 1109

Strict Standards: Declaration of Walker_Comment::start_lvl() should be compatible with Walker::start_lvl(&$output) in /var/www/serverdude.dk/public_html/wp-includes/comment-template.php on line 1266

Strict Standards: Declaration of Walker_Comment::end_lvl() should be compatible with Walker::end_lvl(&$output) in /var/www/serverdude.dk/public_html/wp-includes/comment-template.php on line 1266

Strict Standards: Declaration of Walker_Comment::start_el() should be compatible with Walker::start_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/comment-template.php on line 1266

Strict Standards: Declaration of Walker_Comment::end_el() should be compatible with Walker::end_el(&$output) in /var/www/serverdude.dk/public_html/wp-includes/comment-template.php on line 1266

Strict Standards: Redefining already defined constructor for class WP_Dependencies in /var/www/serverdude.dk/public_html/wp-includes/class.wp-dependencies.php on line 31

Strict Standards: Redefining already defined constructor for class WP_Http in /var/www/serverdude.dk/public_html/wp-includes/http.php on line 61
Software rant « Serverdude
Deprecated: preg_replace() [function.preg-replace]: The /e modifier is deprecated, use preg_replace_callback instead in /var/www/serverdude.dk/public_html/wp-includes/kses.php on line 1002

Deprecated: preg_replace() [function.preg-replace]: The /e modifier is deprecated, use preg_replace_callback instead in /var/www/serverdude.dk/public_html/wp-includes/kses.php on line 1003

Software rant

Something is rotten in the state of Denmark. Well - to be sure, it’s not just Denmark it is perhaps in the state of the art of programming.

MVC frameworks such as Rails, Grails, and Play! all fall prey to the fallacy of developing to please if not the compiler, then the framework. Don’t get me wrong, I’m not against the MVC pattern, I’m not against rapid development. But the way that the frameworks separate the entities is just plain wrong. At least according to High Cohesion/Low Coupling. It seems we’ve ended up in the low cohesion/indirect high coupling quadrant.

Models aren’t interchangeable, they do not adhere to the same higher ordered abstraction and should not be packaged together.

In the case where you want to reuse some models of a prior project, the separation of entities in that project will not carry over any easy reuse.

Instead of:

Models/
      + A
      + B
Views/
     + A
     + B
Controllers/
          + A
          + B

It seems it would be prudent to have:

A/
 + Model
 + View
 + Controller
B/
 + Model
 + View
 + Controller

And if the entities A and B are independent services, then by all means they should reside in separate modules to heighten the potential of reuse.

Another benefit of this way of packaging is the immediate overview of the project. You open the project, and see that there are 2 entities: A and B. Not that the project is an MVC project.

This is not to say that MVC frameworks are evil and should be shied away from - there are other evils lurking around in other areas, especially in the Java world with annotations, which on their own can be useful, but through 3rd party libraries they form an extreme vendor lock-in.

The other part is the problem of programmers - apparently on any level - forgetting the scientific evidence, e.g. SOLID principles.

Single Responsibility means one thing only. Perhaps this is where Object Oriented Principles breaks down and you have to adopt some functional programming style into the solution.

For lack of better ideas let’s examine Martin Fowler’s EventSourcing example. By the way, I’m all for Event Sourcing - it should just be done right. Sadly I think it is taught wrong. I’m not saying that it won’t work; I’m simply saying it could - and most likely should - be done differently. This is not particularly to point fingers at Martin Fowler, it’s to illustrate that we all do less than optimal things. Focus is directed elsewhere. The real point is to raise awareness and in the hope that we don’t end up with big balls of mud.

class EventProcessor...
  IList log = new ArrayList();
  public void Process(DomainEvent e) {
    e.Process();
    log.Add(e);
  }

class DomainEvent...
  DateTime _recorded, _occurred;
  internal DomainEvent (DateTime occurred) {
    this._occurred = occurred;
    this._recorded = DateTime.Now;
  }
  abstract internal void Process();

class DepartureEvent...
    Port _port;
    Ship _ship;
    internal Port Port   {get { return _port; }}
    internal Ship Ship   {get { return _ship; }}
    internal DepartureEvent(DateTime time, Port port, Ship ship) : base (time)   {
      this._port = port;
      this._ship = ship;
    }
    internal override void Process() {
      Ship.HandleDeparture(this);
    }

class Ship...
  public Port Port;
  public void HandleDeparture(DepartureEvent ev) {
    Port = Port.AT_SEA;
  }

Before the addition of Events the Ship knew about the Port, and most likely the Port knew about the Ships, which is cyclic dependency in itself. With the addition of Events the Ship is now modified - which is a violation of the Open/Closed principle, what’s more: The newly added Events will have to know of Ship and Port - this is fine - but the existing objects will have to know about the new objects, thereby entangling the cyclic dependencies even further.

I do understand the idea behind the Ship knowing which Port if any it is at, an optimized double-link as opposed to examine all the ports and in worst case not find the Ship. But the Port is not part of what makes up a Ship. The solution would be to have a ShipLocationService which ties the Port ID and the Ship ID - basically the Event Sourcing events. Thus a simple query with the known Ship ID should - in O(1) provide the location of the Ship in question. As I see it, then that solution is far superior to the one shown.

Second, if the Ship and Port classes aren’t modified, we should have greater confidence in an update, as the prior solution is untouched, and the addition can be rolled out and back independently.

Furthermore, as the classes for Ship and Port aren’t touched, they can be reused for other services, without the need to update those services as a cascade of changes. I’m not saying they should, only that they could. And I’m not saying that there never will be a need to modify an object definition only that it has to be true to the single responsibility principle.

Naturally for a one-off solution this is overkill, but evidence shows that one-off solution rarely exists, that maintenance is a heavy burden - around 1/3 of the total spent on software. (source)

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.” C.A.R.Hoare

The third part is programming languages. Each and every programming language has flaws in the sense that they force a specific way of doing things. And being habitual people developers assimilate the thought patterns laid out by the language. In this I’m disagreeing with Linus Thorvalds - programming languages actually have a profound impact on the solutions. But the disagreement only goes so far, as I’m agreeing with his “Bad programmes worry about the code. Good programmers worry about data structures and their relationships” E.g. Java without the static Set initializations makes programmers use other data structures.

Java’s requirement to create the folder structure matching the package structure, setting up a file with the correct name, and then naming a method in which the implementation steps for a given solution can reside is detrimental for the progress of development, as there is too much pomp and circumstances - or grinding - associated with this, which has nothing to do with solving a problem.

Thus the programmer can either be careless and get things done with a lot of technical debt - or be meticulous and slow down progress.

It is extremely difficult to convince stakeholders that their working software solution ought to be modified - especially given the track record of software projects (source). I must say that I’m not happy with the statistics and actually quite upset with the comparison of iterative, agile, and lean with the traditional method. To me it seems like the boiling frog anecdote (source).

With a 2/3 average success rate - at best, and probably more likely 1/2 - then the odds of having a continued successful software product after a few versions is diminishing quite rapidly: (2/3)^version. Naturally the Binomial distribution could be used if accepting some failures along the way, but then it would not be continuously successful.

In other words, if a change is to be reasonable, then it should increase the expected value of the product by at least 50% and prudently more than double the value, not counting the cost of development.

continued-success-rate-of-versions

If we can improve on the average success rate, then we can accept less valuable commitments without too much worry. With 90% success rate we can accept 11% increase in value per version, and run 6 versions with an expected continued success above 50% for the last version. Currently we should only accept one version under these criteria. As Dan North says: “Software is a liability.”

Comments are closed.