DEV Community

Cover image for How do you order your functions?

How do you order your functions?

Aral Roca on July 26, 2020

Many linters complain that functionA cannot be declared on bottom of functionB when this is the case: function first(){ second() } function s...
Collapse
 
konstantinklima profile image
Konstantin Klima

Uncle Bob says we should order our functions by abstraction level and I've found that I like that approach best, as the code reads like a book.


function doSomething() {
    readInput()
    writeOutput()
}

function readInput() { 
   lowLevelImplementation()
}

function writeOutput() {}

function lowLevelImplementation() {
    ...
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

About Uncle Bob, it seems that he is quite famous -- duckduckgo.com/?q=Uncle+Bob (the search engine suggested it correctly, without any programming-related keywords)

Collapse
 
konstantinklima profile image
Konstantin Klima

He is considered THE authority on clean code and best practices by a lot of developers and computer scientists and his books constantly appear on must-read lists for developers.
AFAIK, he is the one who originally put together the SOLID principle rules and is one of the creators of agile development.
I also love his writing style, very enjoyable to read ^^

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

Yes, he even wrote one of the things in "97 Things Every Programmer Should KNow", which is probably the book title I throw around by far the most (It really is a gold mine though)

Collapse
 
deebeast profile image
Deepak Vishwakarma

I really like what is suggested . It's one of the key concepts of functional programming too.

Collapse
 
etienneburdet profile image
Etienne Burdet

This is what suits the most to. It's much easier to read lower-order functions once you know where they will be called, while most of the time it's fairly easy to infer what they do by their name.

Collapse
 
aralroca profile image
Aral Roca

Yep! I like it. This is clear to read

Collapse
 
ben profile image
Ben Halpern

This is how I do things

Collapse
 
nilia1972 profile image
nilia1972

Yes, it is clear and simple.

Collapse
 
helderberto profile image
Helder Burato Berto

I always declare first and call then later, like the following:

function second() {}

function first() {
  second();
}

Considering the second is a dependency from first, personally I think it's more readable.

Collapse
 
adiluddin profile image
Adil • Edited

There's something called as Stepdown rule when it comes to writing functions, here's an example:
dzone.com/articles/the-stepdown-rule
This is also suggested by uncle Bob in the clean code handbook.

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

But, does it even possible for some languages that have functions are first class citizen, such as Python?

I mean, class methods?, no problem. JavaScript with function keyword?, no problem. But what about the others?

Collapse
 
gwutama profile image
Galuh Utama

Python, yes. C/C++, yes (you declare the functions first in header). Bash, yes.

Thread Thread
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

Python?

This does not work. (If you put if __name__ == '__main__': at the bottom, it will work, though.)

But this does work in JavaScript. Don't know whether I should do it, though.

makeBreakfast()

def makeBreakfast():
  addEggs()
  cook()
  serve()


def addEggs():
  print("""
  fridge
    .getEggs()
    .forEach(egg -> fryingPan.add(egg.open());
  """)

def cook():
  print("""
  fryingPan.mixContents();
    fryingPan.add(salt.getABit());
    fryingPan.mixContents();
  """)

def serve():
  print("""
  wife.give(fryingPan.getContents(20, PERCENT));
    self.give(fryingPan.getContents(80, PERCENT)); // huehuehue
  """)
Thread Thread
 
gwutama profile image
Galuh Utama

Well that's true.

if __name__

must be written on the bottom. However here's I always do it in python:

#!/usr/bin/env python

def main():
    foo()

def foo():
    print("foo")
    hello()

def hello():
    print("Hello, world!")

if __name__ == "__main__":
    main()

Ordering functions from the highest abstraction to lower works this way.

Thread Thread
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

It is always nice to see a runnable code, and if possible, IRL open source projects. Thanks.

And I also want to say, this also works regardless of being outer scoped.

#!/usr/bin/env python

def foo():
    print("foo")
    hello()

def hello():
    print("Hello, world!")

if __name__ == "__main__":
    foo()
  • I think main() has no real meaning. But if __name__ == "__main__": as well as anything in __main__.py do. main() may help in unittesting, though.
  • About #!/usr/bin/env python, at least for me, it is rare to make Python only one-file. Often, there are modules, probably with top-level app.py. So, I only put shebang once.
Thread Thread
 
gwutama profile image
Galuh Utama • Edited

Yes, main() is just common to see. By no means it has to be called main().

Here's an example from docker-compose:

The entry point is here

It doesn't even use the usual if __name__ ...

from compose.cli.main import main

main()

which calls this module

Check out the main() function there. It's defined at the top of the file and it calls lower level functions there.

Regarding the hash bang, yes I just do it out of habit. I often use python to replace bash to write small command line tools, which in my case, often in single files.

Collapse
 
bytebodger profile image
Adam Nathaniel Davis • Edited

I always order them like this:

function first(){
  second()
  third()
}

function fourth(){
  // Whatever
}

function second(){
  fourth()
}

function third(){
  // Whatever
}

In other words, I order them alphabetically. Granted, it looks a little strange in this example, because these function names seem to imply a specific order. But that's not the case in "real" code.

I hate having to scroll up-then-down-then-up again as I search for a given function. So I put everything in alphabetical order. I even wrote a whole article about this a little while back:

dev.to/bytebodger/sorting-code-alp...

Collapse
 
aralroca profile image
Aral Roca

Oh nice. I sort imports alphabetically, but not functions. But It looks another alternative.

As a curiosity, if you have a module with a main function (export default) and other functions that are used by the "main" function. Do you put the main function at the top and the others at the bottom in alphabetical order, or do you also order the "main" function?

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

Well, I spend most of my time doing React, which leverages functional components (very similar to a class). So with components, the component itself is the default export. Components can contain any number of functions. Inside the component, I always arrange my functions alphabetically.

In those cases where I'm defining standalone functions to be used across the app, I only ever define one function per file.

Collapse
 
savagepixie profile image
SavagePixie

I do a mix of alphabetical and abstraction order.

At the top I put all the helper functions sorted alphabetically and at the bottom the functions that the module exports (also sorted alphabetically).

For the same reason, I hate having to hunt functions up and down. Alphabetical order makes it much easier.

Collapse
 
pentacular profile image
pentacular

Honestly, I think that if you do not have too many functions grouped together, the order does not matter.

The corollary being that if you care about the order of the functions, perhaps you have too many grouped together.

Perhaps the answer is to break them up into smaller, logical groups?

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

Classical functions declaration all at the bottom, including locals. Of course this seems to work only in Javascript.

Eslint standard does not complain, though.

BTW, why I see no semi yet in this thread? Which defaults do you all use?

Collapse
 
eljayadobe profile image
Eljay-Adobe

"...no semi..." as in no semicolons?

I use JavaScript Standard Style, which omits optional superflouous semicolons.

Ever since Douglas Crockford called Bootstrap's omitting semicolons "That is insanely stupid code. I am not going to dumb down JSMin for this case." I was convinced that omitting optional superfluous semicolons was the right thing to do. Then, reinforced after Brendan Eich agreed with Douglas Crockford in spirit and tone regarding semicolon omission as poor style.

Right or wrong, automatic semicolon insertion is part of the language, and has to be taken into account for both those in favor of putting semicolons in explicitly, and for those in favor of omitting semicolons where possible which means that are inserted implicitly.

The "where possible" is the crux of the matter, and can burn both sides.

Semicolons in JavaScript are not optional. When omitted — where it is possible to omit them — they are implicit, and automatically inserted for you.

Being aware of the edge cases where they are needed is the important part.

Collapse
 
simondell profile image
Simon Dell

I agree with your suggestion. "top to bottom" is much easier to read.

I rarely write code this way, however. I tend to group my functions around the domain they operate on, and then alphabetically, except where that causes linters to complain. I think you've managed to show me I need to rework my linter rules ;-)

Generally, however, I think lists of any programming token (functions, imports, parameters, members of an object/dictionary) are best entered in alphabetical order, when you work in a team. It's a very easy rule to remember and follow, and prevents wasted time during code review. It also supports how git works (line by line), so you have fewer conflicts when merging branches.

Collapse
 
aguynamedjonas profile image
Jonas Peeck

Clean Code suggests an awesome analogy imho of ordering functions like they are an article in a newspaper:

Most important statement up top, then comes the subheadline, then the first paragraph that tells you everything you need to know and then the gritty details.

So essentially order by abstraction layer as others suggested, enhanced by thinking about what the most important LOC in that file are that somebody opening this file needs to read first.

Collapse
 
fhammerschmidt profile image
Florian Hammerschmidt

Use a language which does not even allow to use a value or function before declaration (i.e. the compiler yields an error) and structure the low-level internals into nested modules.

For instance in ReasonML:

module Something = {
  let readInput = () => ();
  let writeOutput = () => ();
};

let doSomething = () => {
  Something.readInput();
  Something.writeOutput();
};

This makes it also very easy to factor out the module into a separate file later, when the file at hand becomes too big, because a file in ReasonML is also just a module.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

I've gotten used to structuring my code files so that helper functions go at the top and library functions then go at the bottom. Since I mostly code Lua, I can call any library function from any other, but with helper functions I don't really mind structuring them so the most low-level ones go on top.

Collapse
 
elmuerte profile image
Michiel Hendriks

The deeper is goes, the lower it gets.

Collapse
 
perpetual_education profile image
perpetual . education

Order of importance. Just like CSS. But - not saying that's the 'best' way.

Collapse
 
msamgan profile image
Mohammed Samgan Khan

according to the PRS standards function which are same should be close to each other. so this is a better paractice.

Collapse
 
functional_js profile image
Functional Javascript • Edited

I use arrow funcs exclusively, thus ordering by definition before invocation is runtime enforced. ;-)

Most of my modules have one func.
My utility modules have many funcs, but order doesn't matter since there is no dependencies between any of them; if anything they're arranged by general similarities.

But that's also trivial because I get to a func by hitting F12, or alt-F12 to get preview-popup. If I'm in the utility module, I use ctrl/cmd-shift-period to pull up the list of funcs. You can also type in that list to highlight the func you want, then hit enter to go to it.

So where a func is inside of a code file is the least of my concerns.
The more common concern is pondering, "Do want to pull this func out into its own module?"

Collapse
 
aralroca profile image
Aral Roca

BTW; 1 function per file is not a valid answer 😊

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt

circular dependencies made undefined is without doubt, another problem.