Breaking up classes and methods into smaller units

During code reviews a couple devs have recommended I break up my methods into smaller methods.

Their justification was (1) increased readability and (2) the back trace that comes back from production showing the method name is more specific to the line of code that failed. There may have also been some colorful words about functional programming.

Additionally I think I may have failed an interview a while back because I didn’t give an acceptable answer about when to break things up.

My inclination is that when I see a bunch of methods in a class or across a bunch of files, it isn’t clear to me how they flow together, and how many times each one gets called. I don’t really have a good feel for the linearity of it as quickly just by eye-balling it.

The other thing is a lot of people seem to place a premium of organization over content (e.g. ‘Look at how organized my sock drawer is!’ Me: ‘Overall, I think I can get to my socks faster if you count the time it took to organize them’).

Our business requirements are not very stable. I’m afraid that if the classes/methods are very granular it will take longer to refactor to requirement changes. I’m not sure how much of a factor this should be.

Anyway, computer science is part art / part science, but I’m not sure how much this applies to this issue.

EDIT:

Check out: What is the ideal length of a method for you?

3

It’s closely tied with the idea behind unit testing … where “unit” is a hotly contested and poorly defined term. Basically, if you start chunking your code up, at what point do you hit nice little bundles that behave in unsurprising ways? It’s nice to exercise your conceptual units before they get blended into the whole.

In OO, it’s also guided by the Single Responsibility Principle, which bascially says that each class should do one thing and one thing well. That is, you should be able to think about each thing in your system easily without having to resort to using your fingers and toes to count.

At the core, I look at my code and try to identify distinct ideas. Usually these ideas have some properties, and a set of operations that make sense on them. If the idea really is just an idea, then the odds of it being useful in more than one place go up.

When you’ve defined code around the data and operations related to core ideas, you can start putting your clean, sharply-defined ideas together in a way that turns into a big messy program.

Let’s say you’re writing a Sock Drawer app. Some of the ideas that you’ll need to model are: a dresser, a drawer, a sock, a pair of socks. Each of those is pretty easy to define in terms of their attributes and operations you can perform on them. Once you have those things defined, written, and tested, then you can start putting them together to make a whole system.

Let’s say that version 2.0 of your Sock Drawer requires a rocket-assisted conveyer belt and a black-box AI module which selects socks for you based on the weather, from all over the world. If you have your core ideas in place, then you can start wrapping them in AI logic and extended functionality. Your system can grow by adding richness in the interaction of core ideas, without fussing with the core ideas themselves too much.

A couple of practical exercises that will help break things up are: 1) limit the size of your coding units, 2) limit the amount of indentation you allow yourself (no more than 3 nested levels!!!!!! but try no more than 2 as an exercise) 3) follow “don’t repeat yourself” religiously.

All of these are fairly objective criteria that will force you to think harder about how to find patterns and consolidate like code into cohesive bundles.

5

You are missing three big points. First, using well-named and well-designed smaller functions means you usually don’t have to understand how all the functions flow together and how often they are called. You look at the level of abstraction you need, and don’t try to hold the entire call stack in your head at once.

For example, if I’m reading an algorithm and come across number.isPrime, I have a pretty good idea what that does. I can debug perfectly fine at that layer of abstraction and only have to delve a layer deeper if I discover it is returning incorrect results. Admittedly, it’s a little extra work if I do have to go there, but usually I don’t.

On the other hand, if the original author didn’t break out isPrime into its own function, I have no choice but to slog through that extra layer of abstraction every single time.

Second, smaller functions are easier to test and debug, because they only do one thing, and therefore are more likely to be correct. isPrime is pretty easy to test with some sample data at boundary conditions, then you can trust it after that point. If it’s buried inline deep inside another function, it’s difficult to isolate where any problems are.

Finally, smaller functions are more likely to be reusable. When you use smaller functions, you will naturally find places to avoid duplication, and it will be easy to consolidate. Also, the reused functions are already tested and debugged, saving you time.

It’s not so much the difference between an organized or unorganized sock drawer as between a sock drawer and a knitting machine. Even if a knitting machine can spit out 10 socks per minute, that’s still not the abstraction level you want when you’re getting dressed in the morning.

When I first started coding (and still a little now) I thought much the same way as you:

Why break things apart, when it’s so much easier to find everything in this one place?

Until I started getting in bigger and bigger and bigger applications. Now, writing my own content from scratch, I am seeing more and more opportunity to segment, decouple and reuse.

Mentally you have to wrap your head around the procedural (unless threadding) nature of how the computer will run your application. It’s going to init, fetch, cache and output in the way you told it to, even when using objects. So if it helps, as it does for me, arrange your files visually in the way you expect them to flow logically.

For example I might have 3 files open at a time: Model, View, Template.

The tabs will be in my IDE in that order. My brain reads that as “get data”, “do something with data”, “display data”.

Then, within each of those files the classes, and their methods, are organized in a similar way. While it’s not specifically necessary to have __init__ or main() in a specific order in most languages it certainly makes sense to put that thing first when you are writing. Now extrapolate that same thought process out against the entire project.

As you are writing and find yourself saying, “Hm, I need to do xzy here.” check whether xyz was already written. It if was pull that thing out of wherever it was, make it into a reusable function. Now both methods do the exact same thing and you saved yourself time. Both now and in the future when you need to do xyz again.

In any good language it’s easy to compose two small functions into a bigger function, but there’s no way to split a big function into two smaller functions. Likewise, it’s easier to understand a big function in terms of what smaller functions do than it is to keep track of all the state in a big monolithic function. Human memory is at a premium; if we could reliably track large amounts of data we’d just code in assembly.

2

Besides the other good answers above, I’d suggest you check into several studies of software development that demonstrate that highly cohesive functions are easier to understand and reason about. The more ideas that are jammed into one function/class/module the lower the cohesion. Lower cohesion (among other things) leads to lower rates of comprehension.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật