“static” as a semantic clue about statelessness?

I’ve recently undertaken a refactoring of a medium sized project in Java to go back and add unit tests. When I realized what a pain it was to mock singletons and statics, I finally “got” what I’ve been reading about them all this time. (I’m one of those people that needs to learn from experience. Oh well.)

So, now that I’m using Spring to create the objects and wire them around, I’m getting rid of static keywords left and right. (If I could potentially want to mock it, it’s not really static in the same sense that Math.abs() is, right?) The thing is, I had gotten into the habit of using static to denote that a method didn’t rely on any object state. For example:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
public static Thingy newThingy(InputType input) {
new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
}
}
//called as...
ThirdPartyLibraryWrapper.newThingy(input);
</code>
<code>//Before import com.thirdparty.ThirdPartyLibrary.Thingy; public class ThirdPartyLibraryWrapper { public static Thingy newThingy(InputType input) { new Thingy.Builder().withInput(input).alwaysFrobnicate().build(); } } //called as... ThirdPartyLibraryWrapper.newThingy(input); </code>
//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
    public static Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
ThirdPartyLibraryWrapper.newThingy(input);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>//After
public class ThirdPartyFactory {
public Thingy newThingy(InputType input) {
new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
}
}
//called as...
thirdPartyFactoryInstance.newThingy(input);
</code>
<code>//After public class ThirdPartyFactory { public Thingy newThingy(InputType input) { new Thingy.Builder().withInput(input).alwaysFrobnicate().build(); } } //called as... thirdPartyFactoryInstance.newThingy(input); </code>
//After
public class ThirdPartyFactory {
    public Thingy newThingy(InputType input) {
         new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
    }
}

//called as...
thirdPartyFactoryInstance.newThingy(input);

So, here’s where it gets touchy-feely. I liked the old way because the capital letter told me that, just like Math.sin(x), ThirdPartyLibraryWrapper.newThingy(x) did the same thing the same way every time. There’s no object state to change how the object does what I’m asking it to do. Here are some possible answers I’m considering.

  • Nobody else feels this way so there’s something wrong with me. Maybe I just haven’t really internalized the OO way of doing things! Maybe I’m writing in Java but thinking in FORTRAN or somesuch. (Which would be impressive since I’ve never written FORTRAN.)
  • Maybe I’m using staticness as a sort of proxy for immutability for
    the purposes of reasoning about code. That being said, what clues
    should I have in my code for someone coming along to maintain it to know what’s stateful and what’s not?
  • Perhaps this should just come for free if I choose good object metaphors? e.g. thingyWrapper doesn’t sound like it has state indepdent of the wrapped Thingy which may itself be mutable. Similarly, a thingyFactory sounds like it should be immutable but could have different strategies that are chosen among at creation.

I liked the old way because the capital letter told me that, just like
Math.sin(x), ThirdPartyLibraryWrapper.newThingy(x) did the same thing
the same way every time. There’s no object state to change how the
object does what I’m asking it to do.

That is the right way to do it, yes. That said, static confers no guarantees of immutability or state persistence. That you use it as a suggestion for such guarantees does make sense, but it is by no means assured.

Consider the following:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public static class Logger
{
public static int LogLevel { get; set; }
public static void Log(string message, int logLevel)
{
if (logLevel >= LogLevel)
{
// logs the message, but only if it is important enough.
}
}
}
</code>
<code>public static class Logger { public static int LogLevel { get; set; } public static void Log(string message, int logLevel) { if (logLevel >= LogLevel) { // logs the message, but only if it is important enough. } } } </code>
public static class Logger
{
    public static int LogLevel { get; set; }

    public static void Log(string message, int logLevel)
    {
        if (logLevel >= LogLevel)
        {
            // logs the message, but only if it is important enough.
        }
    }
}

This class not only holds state, but the behavior of the Logger.Log() method changes when that state is changed. It’s a perfectly legitimate exercise of a static class pattern, but it has none of the semantic guarantees that you are suggesting.

2

In my opinion what you are saying – all static functions to be nullipotent – is a good OO way of writing code in most cases but I do not believe that when you look at a static function you should automatically assume that it does not have side effects. The situation may be more complex; take for example the function Class.forName(String) which appears to be stateless but it actually loads a class into the memory and eventually instantiates static fields/run static initializer; this is an example of idempotent function (eventual calls after the first one make no difference) but it is not a pure function (it cannot be said that it does not have side-effects). This is also a good choice, but there might be cases in which three distinct calls to the same function yield three different results; for example if you call Thread.currentThread() in a multi-threaded application there is no guarantee you will receive the same thread every time.

That being said, what clues should I have in my code for someone
coming along to maintain it to know what’s stateful and what’s not?

A proper solution is to document (Javadoc for example); also, from the name of the function and from what it does sometimes it can be inferred that the static function is a pure function. For example there is no reason for someone to believe that Assert.assertTrue(boolean) from JUnit would change some state somewhere. On the other hand when a function like System.clearProperty(String) is called, it is pretty obvious that there will be side-effects.

2

That being said, what clues should I have in my code for someone coming along to maintain it to know what’s stateful and what’s not?

You can make them static. FxCop over in the C# world will push you to make things static that do no reference member variables. This is the correct thing to do (usually).

When I realized what a pain it was to mock singletons and statics, I finally “got” what I’ve been reading about them all this time.

Moving all of them to instances is perhaps not the right approach. Instead, decouple the dependencies on static methods from the classes that use them. You can test the static methods in isolation, and then replace the dependency in the consumers when they need to be tested.

2

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