New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coding Style Guide #823

Open
AndrewM- opened this Issue Oct 9, 2015 · 14 comments

Comments

Projects
None yet
6 participants
@AndrewM-

AndrewM- commented Oct 9, 2015

I have been developing in ms-access since 1.0 and write big applications. However programming has evolved and I am finding myself encountering rafts of concepts that are ported in from other environments. Use of the MVC development patten was promoted by one of the lead RD developers and was actually how I found RD. Yesterday, I came across valuable comments on Hungarian notation, flattening of unnecessary nesting and quite a bit more. These things might be intuitive to highly experienced developers but are not the bulk of casual ms-access developers especially ones who are isolated from the developer community.

I think for the health of the Rubberduck project, there needs to be an application development style guide that raises and deals with these questions so that lead developers do not have to answer them. Some of the style guide could come from Code Review responses that have been authored by the Rubberduck team. Rubberduck is essentially providing a bridge between VBA land where people just get in and have a go and the VS land where if you don't know a great deal about software development, you just waste your time and burn. Rubberduck will put a lot of people on a big learning curve and this will result in a lot of questions.

Currently I am writing manifestos on other ms-access sites mainly to find out in an attempt to find out if there are flaws in my coding style (did one yesterday suggesting Hungarian notation was passed its use-by date). Will have to try Code Review in future.

Firstly do you and the other lead developers think that providing a programming style guide aimed at people who are encountering a professional development environment for the first time and who don't get all of the principles implicit in Rubberduck is something that should be done and something that should be in a wiki connected to the Rubberduck site? Secondly, I am happy to provide some of the material that fills the void between professional developers like yourself who know why things are done the way they are and casual developers like myself who still working things out.

Cheers,

Andrew

@retailcoder

This comment has been minimized.

Member

retailcoder commented Oct 10, 2015

First of all, thanks for the compliments!

One of the features we put on the roadmap early on, and haven't gotten to yet, is a tool to facilitate posting VBA code on Code Review Stack Exchange - the site where Rubberduck started.

Another way RD could help, could be some kind of "did you know?" / "tips & tricks" feature, that we could pop up... and also at one point the Rubberduck News WP blog will eventually turn into that, too.

But in my experience, nothing beats getting your VBA code peer reviewed on Stack Exchange.

@AndrewM-

This comment has been minimized.

AndrewM- commented Oct 10, 2015

I have just tried out RubberDucks tutorial on writing testable code that was posted on Stackexchange http://stackoverflow.com/questions/47400/best-way-to-test-a-ms-access-application. Trouble was it took me half an hour to find it again as I naturally was distracted by the need to check out what rubberduck was. Most of the really good posts are very hard to search for so some kind of table of contents is warranted IMO. Ruby on Rails has a philosophy of convention over configuration and the Rubberduck project has a philosophy too and that philosophy is just as important as the software. For example coding for to make unit testing possible. What I am suggesting is the strong lessons that emerge from the Code Review site be linked to a wiki on the Rubberduck site. I am happy to do make a start at this, as I am reading these reviews, then going and playing with the ideas. Later on I will put my best attempt at good code on the Code Review site to see how it stands up.

So to answer your question tips and tricks are probably not what would help me. Sitting down and reading longer examples such as Rubberducks post on writing testable code is the shot. I just need to be able to find these gems more easily.

@rubberduck203

This comment has been minimized.

Member

rubberduck203 commented Oct 10, 2015

I can see that and I think I need to take that SO post of mine and make it a blog post, then link to it from the wiki. Or cross post it on Rubberduck news.

One thing that probably needs some work is the Code Inspection wiki.

  1. It probably needs to be updated to include newly added inspections.
  2. It covers the what pretty well, but not much of the why. That could certainly be improved.
@retailcoder

This comment has been minimized.

Member

retailcoder commented Oct 10, 2015

@ckuhn203 one recurring thought I've had, is to make some room to build-in the "why" of each code inspection, so that you could click some "?" icon and get a thorough description of when an inspection is applicable, when it's safe to ignore, why each quickfix is what it is and why applying them leads to overall better code.

@daFreeMan

This comment has been minimized.

Contributor

daFreeMan commented Oct 29, 2015

@AndrewM- you've hit the nail on the head! I've been coding for 20+ years, and the majority of my style hasn't really changed in that time. I've posted several questions on the Rubberducking chat about why things were being flagged and what was wrong with the way I was doing it.

I think that a why "?" would be infinitely helpful and instructive.

@AndrewM-

This comment has been minimized.

AndrewM- commented Oct 29, 2015

I am finally getting my head around all this stuff too. My ms-access applications are fundamentally client-server or two tier applications. Git and unit testing push toward 3-tier applications where there is an abstracted business layer between screen forms and the database. I have been finding it quite hard to make my applications conform to this pattern and now consider my screen forms as a thick client that are legally allowed to do all user input validation and user interface updates such as when a user makes a selection that enables a bunch of form fields. The business layer processes then processes the data the users have entered. Events are raised only by forms and the business layer uses only functions/ layers of functions. I have looked high and low for information on application architectural patterns that can be used in ms-access and found nothing. I pretty much have developed my own pattern now and it is procedural and is designed so that I can leave the application code accessible to users so that they can do their own bug fixes and feature additions. Consequently I am staying away from a number of advanced methods e.g. delegating event handlers on the fly. In conclusion, the tools used influence the application architecture and hence it would be good to have a style guide. So far the MS-Access Bible by Wiley is the best I have found but it does not cover issues such as separation of concerns, which I would like to know more about implementing in a ms-access environment.

@rubberduck203

This comment has been minimized.

Member

rubberduck203 commented Oct 30, 2015

Great. @AndrewM- just convinced me that I need to write a book on the topic. Like I didn't have enough to do... =P

For the record, your "thick client" approach works well. That's because it was designed to create applications without any code at all. Doing what people like us do with it is, honestly, a bit abusive. It's no surprise that it's a bit difficult.

@rubberduck203

This comment has been minimized.

Member

rubberduck203 commented Oct 30, 2015

My implementations of a three tiered architecture relied heavily on adodb and a SQL server backend. I didn't leverage access itself much. Both methods have their pros & cons.

If also remind you that there's nothing wrong with leveraging the power of the built in forms. You can consider it client side validation and a "view".

@retailcoder

This comment has been minimized.

Member

retailcoder commented Oct 30, 2015

Rubberduck's unit testing feature treats VBA as a fully capable OOP language, despite the lack of inheritance; it is possible to write decoupled, object-oriented code in VBA.

Perhaps one of the most useful refactoring tool we could make for refactoring procedural into object-oriented code, is a way to extract a class out of a selection of methods in a module, and then a way to extract an interface out of a class' public members: in conjunction with the extract method refactoring, Rubberduck makes it easier to separate concerns and adhere to OOP principles, resulting in testable code. And then it gives you the tools to write the tests, and run them.

Logic that requires user interaction with a GUI, can't be unit tested. So Rubberduck ultimately wants to help you take that logic out of the UI and into testable objects.

At one point Rubberduck will be able to create and implement wrapper interfaces around, say, a Worksheet object, or even a MsgBox call. A mock version to use as fake providers in tests, and a default implementation that merely wraps properties and functions like Range(), and methods like .Show() - whatever.

The core concept here is abstraction: these wrappers abstract away a boundary between the code you want to test, and the code that interferes with it - UI / host application's API, file system, databases, etc. - the dependencies that you want under control in a unit test.

There are no constructors in VBA, but constructor injection isn't the only type of Dependency Injection.

The main problem with a VBA project written in a full-blown OOP style, is navigating it - the VBE's Project Explorer gives us no way of regrouping classes and modules into "folders". Rubberduck can - and will - change that, by introducing @namespace annotations, and interpreting them in the Code Explorer as folders: @namespace Foo.Bar in a module's declarations section would have that module show up inside a folder called 'Bar' which is itself inside a folder called 'Foo'.

So heck yeah, the tools used influence the application architecture!

I need to blog about this.

@AndrewM-

This comment has been minimized.

AndrewM- commented Oct 30, 2015

@ckuhn203 Thanks. Anyone who is non-professional developer (i.e. they actually do engineering or science for a living) lives in fear of sys admins who can ask questions such as has that been unit tested. You have had the same kind of crap from same kind of people who think that VB is not a serious computing language or open-source projects are not real experience. I have followed up the unit testing trail and reached this point. http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf, This from Mr. Ruby on Rails, http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html and this open conversation from people trying to figure out when and when not to unit test. https://news.ycombinator.com/item?id=7633254.

The question that is nowhere to be found is which role has the responsibility for making sure that working code is not handed bad data, the caller or the receiving procedure. This is a critical question in regard to unit testing. If it is impossible for a receiving procedure to be handed bad data, then it does not need unit tests that foist bad data on the procedure to see what it does. So I am thinking that the input parameters to the procedure should be typed to prevent bad data getting in, for example passing date as dates, rather than dates as strings, as that automatically prevents a lot of errors. Function parameters should act as a kind of bottleneck that blocks bad data to the extent possible. Unit tests could then concentrate on bad data that can slip through such as null dates. I typically use heaps of validation as validation is necessary to create meaningful error messages. The validation is in the receiver just in case I forget to validate the parameters before passing them. And the validation is also in the caller, usually the screen form or a business module directly called by the form as it make sense to abort a bad call before it begins.

@AndrewM-

This comment has been minimized.

AndrewM- commented Oct 30, 2015

Found the concept that I was missing. It is design by contract. https://en.wikipedia.org/wiki/Design_by_contract. Wkipedia is a bit obtuse so I found something better. http://stackoverflow.com/questions/481312/design-by-contract-vs-test-driven-development.

@retailcoder

This comment has been minimized.

Member

retailcoder commented Oct 30, 2015

@AndrewM- you could extract that validation functionality into a class dedicated to validation, exposing public methods for validating different things given some input: that validation functionality can then be unit-tested and you get to write code is to assert correctness with all the possible bad input, and with some of the possible correct input, too! The UI can "safely" be coupled with that functionality, it's tested code - if something goes wrong with the UI logic, you know the validation code works as expected as long as the tests pass.

@AndrewM-

This comment has been minimized.

AndrewM- commented Oct 30, 2015

@retailcoder My coding has come a long way in recent days, thanks in part to assistance from the RubberDuck team. That is a good idea about the validation. Before using a hard drive, I check that the Volume Serial Number has not changed as someone can remove a USB drive and plug in another. That sort of validation would be ideal candidate for extraction and unit testing.

I have also thought of another testing idea. I can put a flag into each function that records when its contract is broken and then logs the details. That would give me a way of discovering things that go bad at the bottom of a long call stack. That would give me a way of finding non-fatal errors that I currently allow to fail silently. For example, if I can't locate a resource such as a thumbnail image because the filespec created by my code is jibberish (at the moment this looks the same as when the thumbnail does not exist). I don't want to raise an error just because one thumbnail is missing but it would be nice to log these events for future examination. Adding the flag is each procedure is trivial as I currently use user defined types/objects for return values so can add a new field to the Type definition and have it available in all procedures. Unit testing would help in this case but having the ability to find errors that got though unit testing would be good.

@retailcoder

This comment has been minimized.

Member

retailcoder commented Jan 13, 2017

If anywhere this would belong in the wiki.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment