94

In Code Complete page 25, it's said that it's a good idea to be able to easily replace the regular user interface classes by a command line one.

Knowing its advantages for testing, what about the problems it may bring?

Will this extra work really pay off for web and mobile projects? What about small and medium projects; do the same rules apply? What if it makes your design more complex?

9
  • 2
    In Perl, this is just what tools like MooseX::Getopt and Plack::Handler::CLI are for.
    – Ether
    Aug 22, 2012 at 14:17
  • 4
    If you build your program with a CLI first, the UI can be layered on top of it, giving much more flexibility than a UI that's deeply embedded in the program. This is much the same for web services.
    – zzzzBov
    Aug 22, 2012 at 14:26
  • 29
    Always is a strong word. Aug 22, 2012 at 14:46
  • 9
    Please note the original quote, which is: "The architecture should be modularized so that a new user interface can be substituted without affecting the business rules and output parts of the program. For example, the architecture should make it fairly easy to lop off a group of interactive interface classes and plug in a group of command line classes." So CC does not say you should prepare for replacing a GUI with a command line, it just says the architecture should accomodate changing the UI. The GUI->command line thing is just an example.
    – sleske
    Aug 24, 2012 at 12:22
  • 2
    @Vandell I have the Second Edition of Code Complete and this is not mentioned on page 25. Which edition are you referring to?
    – JW01
    Aug 30, 2012 at 15:52

17 Answers 17

43

Being able to reuse functionality under different interfaces (e.g. GUI vs CLI vs REST) is not always necessary but nice to have and enable serendipitous reuse for a system, as other people find new ways to interact with it.

This has a few drawbacks that need to be weighted:

  1. It'll require additional abstraction layers (sometimes even tiers). While having these layers is good engineering practice they have an additional cost in development, understanding that may not lead to reduce effort in other areas (e.g. maintenance, reuse, testing) so it's worth to ponder a bit about it.
  2. Flow that's optimal for a medium may be awful for others. If the functionality was designed to support a GUI it may be too chatty for the web. Not all functionality is worthwhile in every medium.
  3. There's a trap in trying to define a generic converter between services and user interface, so one can define the service contract and derive automatically (or as much as possible) the UI for all mediums. Many projects wasted too much effort trying to build such frameworks and adding every possible customization to it as the requirements changed.

Having said that, in my experience implementing such layers always ended up paying the effort. In a couple of cases I managed to deploy systems on time because we ended up having to swap media (e.g. from Web Services integration to UI) a few weeks before the due date.

2
  • 2
    As other comments have noted, it should increase code cohesion and reduce coupling. Both of these should make your code simpler, and easier to test. Flow is more a GUI concept, and usually should not be present in other functionality.
    – BillThor
    Aug 23, 2012 at 1:29
  • I can't believe this hasn't been mentioned yet but this is the essence of the Model-View-Controller architecture. The point is to be able to swap out views and controllers at will, to reduce coupling as @BillThor says. This is the best use case for MVC.
    – user7433
    Oct 8, 2013 at 16:32
110

Completely aside from testing, the obvious advantage to this approach is that it will make your project automatable and scriptable. If I'm able to send command-line commands to a program, I can write up a script to perform complicated tasks much more easily (and more reliably!) than I could create a macro to automate the same thing on a GUI.

Whether or not that's actually worth doing, of course, depends entirely on whether or not you have a lot of users who would want to automate your program.

7
  • 12
    A lot of applications use a plugin model for scripting. Usually the object model is exposed and a language like python is used to write the scripts. I don't think command line parameters will work for a non-trivial app.
    – softveda
    Aug 22, 2012 at 8:33
  • Another benefit can be discoverability. The Ctrl-Shift-P feature of Sublime Text is a fantastic example of this. If there's some obscure functionality I want, rather than having to search through the menus, I just type what I think it would be called, and I can see the command (and the shortcut) and am able to execute it immediately.
    – Adam Iley
    Aug 22, 2012 at 13:39
  • OpenDJ, an open source, java based LDAP server is a great example of this: the command line for every modification you do in the GUI is available in the confirm dialog box.
    – Franck
    Aug 22, 2012 at 14:12
  • 1
    @Marnixv.R.: gestures are merely a convenient way to perform some action that could be specified by a command, e.g. 'Zoom in on 35.73N 118.23W'. A drawing could be input as commands, although it would be inconvenient. Still I think there is great utility in a conveniently scriptable interface, and very little labor needed to create one. Aug 22, 2012 at 15:36
  • 7
    +1: Another key advantage is that it makes it easy to log the user actions, simplifying reproduction of production problems. Aug 22, 2012 at 18:41
81

It's not extra work, just different work. If you do it right, not only will it not make it more complex, it will make it simpler because it will force you to decouple your design. Whether or not you actually implement the CLI, your design will be better off for making it possible to do so.

2
  • 5
    -1 for several completely incorrect statements. Of course it will make it more complex. It is, after all, an additional requirement/feature. Aug 31, 2012 at 0:10
  • @BorisYankov I think he meant "complicated" instead of "complex" - they sound similar and have overlap in meaning, so they're easy to confuse on occasion
    – Izkata
    Oct 8, 2013 at 15:23
43

One key advantage that doesn't seem to have been mentioned is that being able to do this pretty much enforces strict decoupling of the UI from the underlying code. One key advantage of this is that it means that if you need to significantly change the GUI (say iOS standards to OSX standards, or one graphical engine to another), that's all you need to change, as the underlying code isn't dependent on the layout of the UI. It can't be, because if it was, the command line tools wouldn't work.

Other than that, being able to automate tests is a key advantage.

5
  • Correct me if I'm wrong, but changing from one GUI to another would still require significant work in terms of form validation / showing error messages, setting event handlers, etc. Aug 22, 2012 at 13:36
  • 5
    Yes, but all that validation is part of a good UI, which I've said you need to change. The backend code that stores (for example) the current state of the user's account, the algorithm for searching for items, the game's specific rules, etc. The key thing here is that if I have to switch from mouse/keyboard-based UI to touchscreen UI for a game, I should still be able to use the same backend engine for handling combat calculations and scoring, so I can focus on writing new event handlers that use the same underlying system.
    – deworde
    Aug 22, 2012 at 14:21
  • 2
    that's by no means easy btw, I hate writing event handlers and form validation code much more than business code. (though i agree with you that they should be de coupled the way you described) Aug 22, 2012 at 16:12
  • 2
    @ClickUpvote To an extent it depends how you implement your GUI. A really thin GUI that just sends ValueChanged messages to a support class and receives ValueValid/ValueInvalid messages in response will be much easier to swap out that one that does all the validation in OnTextboxChanged events. Aug 22, 2012 at 19:06
  • @ClickUpvote I quite agree, that's why I want to be able to focus on the thing I like uncorrupted, or give the thing that I hate my full attention, so I can be done with it as soon as possible.
    – deworde
    Feb 4, 2016 at 11:22
17

Yes it's almost always a good idea.

If you follow this approach you will not likely have a business logic or data access in a same thread as GUI, and behind some GUI handler. This reason alone is worth investing in.

2
  • 2
    What would be the advantage of that, if you're writing e.g. a text editor?
    – nikie
    Aug 22, 2012 at 7:47
  • 5
    @nikie Because, for example, you could replace your WYSIWIG text editor view with a plain text or markup based front-end, and as long as it passed the same information to the underlying model, your existing infrastructure would continue to work.
    – deworde
    Aug 22, 2012 at 10:36
5

I think it is a good idea. Additionally being able to write a second, command line front end, ultimately proves the business logic is totally decoupled to any particular application server architecture.

5

The only danger I see in doing this is that to get to a certain part in the UI, the user normally has to traverse other parts of the UI.

Where as the developer can just execute the UI directly. I've seen situations where a developer could not reproduce a users issue until they actually used the product.

So factor that in as well when creating tests.

4

No. Terrible bit of advice.

It's a bit yagni (You aren't going to need it).

Exposing a command line interface is not the same as structuring your app in a way that supports unit testing, or complies with any part of SOLID, or any programming practice I'd recommend.

It doesn't work for any UI that just wouldn't suit a command line interface. MS Paint is a really simple app, but how, in any situation, would you see a benefit to being able to control it from a command line?

It wouldn't help you implement scripting. It would actually hinder any progress in that direction.

The only positive thing is it appeared on page 25, so at least you get a warning that the rest of the book might be, ... smelly. I read it a long time ago and didn't like it, so I am biased.

7
  • 2
    Agreed +100000000
    – user2528
    Aug 23, 2012 at 1:05
  • 5
    Scriptable MSPaint sounds really useful actually.
    – RoundTower
    Aug 23, 2012 at 5:10
  • IMO the best answer. Ever since I follow the "don't implement 'YAGNI'" mantra, I have much more time concentrating on the real work and I have even enough time left to experiment a lot. Trying to be clever in advance has shown me that most of the time the customer wanted some different extension than previously mentioned, so no time wasted on something not needed.
    – topskip
    Aug 23, 2012 at 9:04
  • PSPaint + command line interface = AutoCAD
    – Vorac
    Aug 30, 2012 at 9:27
  • 1
    And to cater for such an eventuality would involve code or design that is not required to solve the original problem. It's advice that could better be phrased as "separate your concerns, consider patterns like MVC/MVP". As it stands it is misleading advice.
    – Ian
    Nov 21, 2012 at 9:47
2

Building on what Mason Wheeler said, being able to interact with an application via a command-line makes it very easy to automate tasks.

This is particularly useful in testing.

To give a practical example, if I want to run automated tests on an application, I may want to install the application automatically. To do this, I might pass in the following parameters, "myApplication.exe /silentinstall".

I might program it so that when I specify this command-line switch, an install is performed silently in the background, without the GUI installer. Any input to the installer (such as the install directory) could be picked up from an XML file perhaps.

Take another example. Microsoft Test Manager GUI (comes with Visual Studio) allows users to launch test runs from its GUI interface, but also provides a command-line interface to do the same thing (using a combination of command-line switches and inputs). This means I can whip together a PowerShell or DOS script to automate the launching of tests, and I could then create a scheduled task so that the scripts are run every night, perhaps.

Some applications have command-line switches which specify for an application to open with certain options (for example, I might use '/maximize' to open the application in a maximized window).

There are plenty of scenarios where a command-line interface could come in use. These are just some examples.

1

Notice the phrase again: "[It']s a good idea to be able to easily replace the regular user interface classes by a command line one". It doesn't mean you have to write a CLI, just that you could do it easily.

So, what it says is that your UI should be decoupled from the rest of the code.

1
  • 2
    I think you intended to do a comment, right? Aug 22, 2012 at 15:27
1

It depends and when I say it depends, it's not just a matter of having a couple edge cases, but it is very dependent upon the application and the target audience. Assuming that we are eliminating games from the equation then there is still a wide array of applications that you may be writing where a command like is unlikely or never going to be implemented. Off the top of my head, any application targeting a mobile (e.g. iOS, Android, etc.) environment is likely going to fall under this heading.

With that in mind, in the general software space, any application that is heavily dependent upon visualization (e.g. PowerPoint, Maya, etc.) is unlikely to ever see a command line replacement be implemented. In fact, in the case of graphics software such as Maya, it is arguable a good mental exercise to determine how a full and proper command line version would work and it may not be possible to do so from a user standpoint. Thus, it is clear that there are definitively common applications that can be encountered where a command like interface is unlikely to ever be seen, or desirable even if scripting of the application may be desirable.

Next, if we look at the suggesting form the standpoint of general software architecture, I can see where it would make sense to periodically ask yourself "How can I access this feature without the user interface?" In general, if there is no way to do it and it is not directly interacting with the user (e.g. gesture input) then you likely have a situation where the overall architecture needs to be improved. In order to allow for ease of testing you are going to want to be able to directly access command without going through the user interface, even though they may not be invoked though a command line. This generally means that a solid API needs to be in place and theoretically a good API should allow for access via command line or user interface. Furthermore, in the long run, you will save yourself time if you need to add a new user interface to the application.

At the end of the day, I think that what the suggestion is trying to get at makes sense (i.e. Have a good API and build your user interface off of that) but the word selection might have been a bit better to get the point across.

2
  • 1
    I don't disagree in general, but one of the great strengths of Maya is the fact that it does, in fact, have a very strong scripting API (originally MELScript, now Python).
    – jwd
    Aug 22, 2012 at 17:39
  • @jwd - Maya is an example I picked because I used it a couple years ago, if you have a better one in the same line of thought let me know. Maybe Bryce although it's not as well know?
    – rjzii
    Aug 22, 2012 at 18:48
0

It depends.

Often we partition our programs as model/view/controllers or model/view/view/model. It seems that the model should permit command line access, but I am not as sure about the controller. Naturally, the view is what is being replaced.

Some difference may exist based on tool chain. Code Complete is a Microsoft Press book, so perhaps you are using Microsoft technologies for this GUI? If so, I think there might be a check box when you create the app for exposing interfaces via COM or DCOM. For some Microsoft technologies, I think resource tables and message passing are pretty intensively coupled with anything the Wizards help you rapidly prototype. I think it is getting better, but if you are maintaining MFC or Forms, it might hurt a bit.

In some cases your GUI based program might be a wrapper around a management interface or might have so little logic of its own, that there is not much to control by command line interface. Building a separate console app might be quicker and still let you script, test or use what is important.

The key point I guess is that the suggestion is not a rule. If you follow it, you should get easier unit and acceptance testing or a fall back interface for when you or a customer might prefer typing instead of clicking. If it pays for itself, do it. Good luck.

3
  • 4
    -1: Code Complete is a language-agnostic book about programming craft.
    – deworde
    Aug 22, 2012 at 10:34
  • 1
    He never said otherwise. Aug 22, 2012 at 13:39
  • And his question was specific to UI development... Your point Mr deworde?
    – Ian
    Aug 22, 2012 at 15:02
0

It depends on how useful the command line program would be. Some things, like plotting a route on a map, or playing a 3-d game, just don't lend themselves to a command-line interface. But other things, like system tools are much better from the command line than from a GUI, for the simple reason that they can be scripted.

Dr. Richard Hipp once said that his ideal GUI operating system was a blank desktop with an icon to open up command windows and another icon to open a web browser. I feel almost the same way. If it would be useful as a command-line program, and not too difficult to build that way, I would do it. The GUI could be a completely separate program, maybe built by someone else!

2
  • Why doesn't plotting a route on a map lend itself to CLI automation? Something like PlotRoute(startPoint, endPoint) is pretty straightforward. Aug 22, 2012 at 17:52
  • @MasonWheeler - I believe it would be more like PlotRoute(startPoint, endPoint, chart) Aug 22, 2012 at 18:39
0

These days (at least for Java) it seems like sooner or later all programs add a web service (SOAP or Ajax or both) sooner or later. So in general yes think that way but a web service front end is more likely than a command line if you want a better mental metaphor... and a more likely one.

0

There's a different way of looking at things. Rather than assuming that a command line is the only way to go, why not assume that speech control might be used instead? An entirely different paradigm is required then.

Before Jobs took over Apple, very sophisticated voice control mechanisms were being explored. Apple squelched this in favor of things like Siri.

Sigh.

Popular and obvious aren't always "best."

1
  • One of the main reasons for the command line is mainly to be able to test and script the functionality of the software. It might get a bit awkward (or at least disk-hoggy) to record audio clips of our voices just to unit test the software or run a batch script.
    – user204677
    Feb 1, 2018 at 8:57
0

This is generally a good idea, yes.

By-metaphor, people may think of this as a form of RESTful design. .... it's not, per se, as a typical (G)UI could involve complex multi-stage transactions like account creation.

Better that one stays away from multi-stage complexity through shopping-cart-like models for transactional setup.

I once programmed a drag'n'drop UI metaphor in the browser. Very complex interaction rules on the back-end to make the UX feel natural. I solved this by making the site an API and the GUI was a full app that generated events upon action. A module caught these events and, on a timer, bundled them into 'API calls' (for network efficiency).

The result was a completely RESTful core system. The second upshot was that I had an interface for 3rd parties, that I could expose using affiliation profiles as per the business model.

-1

One advantage is that you will be forced to think about the flow of the UI from the user perspective. (What am I trying to achieve? What context do I need to set up? Given that context, how do I achieve the goal?)

There's a big difference between "create bank account" and "write ms word document". Even if you don't build a CLI, it may add value just to consider the "CLI context" needed. Models don't just live in the business object model!

Not the answer you're looking for? Browse other questions tagged or ask your own question.